]> git.uio.no Git - u/mrichter/AliRoot.git/blob - HLT/TRD/AliHLTTRDClusterizerComponent.cxx
bugfix: Corrected wrong numbering of supermodules (Theodor)
[u/mrichter/AliRoot.git] / HLT / TRD / AliHLTTRDClusterizerComponent.cxx
1 // $Id$
2
3 /**************************************************************************
4  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
5  *                                                                        *
6  * Authors: Matthias Richter <Matthias.Richter@ift.uib.no>                *
7  *          Timm Steinbeck <timm@kip.uni-heidelberg.de>                   *
8  *          for The ALICE Off-line 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   AliHLTTRDClusterizerComponent.cxx
20     @author Timm Steinbeck, Matthias Richter
21     @date   
22     @brief  A TRDClusterizer processing component for the HLT. */
23
24 // see header file for class documentation                                   //
25 // or                                                                        //
26 // refer to README to build package                                          //
27 // or                                                                        //
28 // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt                          //
29
30 #if __GNUC__ >= 3
31 using namespace std;
32 #endif
33
34 #include "TTree.h"
35 #include "TFile.h"
36 #include "TBranch.h"
37
38 #include "AliHLTTRDClusterizerComponent.h"
39 #include "AliHLTTRDDefinitions.h"
40 #include "AliHLTTRDCluster.h"
41
42 #include "AliGeomManager.h"
43 #include "AliTRDReconstructor.h"
44 #include "AliCDBManager.h"
45 #include "AliCDBStorage.h"
46 #include "AliCDBEntry.h"
47 #include "AliHLTTRDClusterizer.h"
48 #include "AliTRDrecoParam.h"
49 #include "AliTRDrawStreamBase.h"
50 #include "AliTRDcluster.h"
51
52 #include "AliRawReaderMemory.h"
53
54 #ifdef HAVE_VALGRIND_CALLGRIND_H
55 #include <valgrind/callgrind.h>
56 #else
57 #define CALLGRIND_START_INSTRUMENTATION do { } while (0)
58 #define CALLGRIND_STOP_INSTRUMENTATION do { } while (0)
59 #endif
60
61 #include <cstdlib>
62 #include <cerrno>
63 #include <string>
64
65 ClassImp(AliHLTTRDClusterizerComponent)
66    
67 AliHLTTRDClusterizerComponent::AliHLTTRDClusterizerComponent():
68   AliHLTProcessor(),
69   fOutputPercentage(500),
70   fOutputConst(0),
71   fClusterizer(NULL),
72   fRecoParam(NULL),
73   fMemReader(NULL),
74   fReconstructor(NULL),
75   fRecoParamType(-1),
76   fRecoDataType(-1),
77   fRawDataVersion(2),
78   fyPosMethod(1),
79   fgeometryFileName(""),
80   fProcessTracklets(kFALSE),
81   fOfflineMode(kFALSE),
82   fHLTstreamer(kFALSE)
83 {
84   // Default constructor
85
86 }
87
88 AliHLTTRDClusterizerComponent::~AliHLTTRDClusterizerComponent()
89 {
90   // Destructor
91   // Work is Done in DoDeInit()
92 }
93
94
95 const char* AliHLTTRDClusterizerComponent::GetComponentID()
96 {
97   // Return the component ID const char *
98   return "TRDClusterizer"; // The ID of this component
99 }
100
101 void AliHLTTRDClusterizerComponent::GetInputDataTypes( vector<AliHLTComponent_DataType>& list)
102 {
103   // Get the list of input data
104   list.clear(); // We do not have any requirements for our input data type(s).
105   list.push_back( (kAliHLTDataTypeDDLRaw | kAliHLTDataOriginTRD) );
106 }
107
108 AliHLTComponent_DataType AliHLTTRDClusterizerComponent::GetOutputDataType()
109 {
110   // Get the output data type
111   return kAliHLTMultipleDataType;
112 }
113
114 int AliHLTTRDClusterizerComponent::GetOutputDataTypes(AliHLTComponentDataTypeList& tgtList)
115 {
116   // Get the output data type
117   tgtList.clear();
118   tgtList.push_back(AliHLTTRDDefinitions::fgkClusterDataType);
119   tgtList.push_back(AliHLTTRDDefinitions::fgkMCMtrackletDataType);
120   return tgtList.size();
121 }
122
123
124 void AliHLTTRDClusterizerComponent::GetOutputDataSize( unsigned long& constBase, double& inputMultiplier )
125 {
126   // Get the output data size
127   constBase = fOutputConst;
128   inputMultiplier = ((double)fOutputPercentage)/100.0;
129 }
130
131 AliHLTComponent* AliHLTTRDClusterizerComponent::Spawn()
132 {
133   // Spawn function, return new instance of this class
134   return new AliHLTTRDClusterizerComponent;
135 };
136
137 int AliHLTTRDClusterizerComponent::DoInit( int argc, const char** argv )
138 {
139   // perform initialization. We check whether our relative output size is specified in the arguments.
140   int iResult=0;
141   
142   fReconstructor = new AliTRDReconstructor();
143   HLTDebug("TRDReconstructor at 0x%x", fReconstructor);
144
145   TString configuration="";
146   TString argument="";
147   for (int i=0; i<argc && iResult>=0; i++) {
148     argument=argv[i];
149     if (!configuration.IsNull()) configuration+=" ";
150     configuration+=argument;
151   }
152
153   if (!configuration.IsNull()) {
154     iResult=Configure(configuration.Data());
155   } else {
156     iResult=Reconfigure(NULL, NULL);
157   }
158
159   if(!fClusterizer){
160     HLTFatal("Clusterizer was not initialized!");
161     return -1;
162   }
163
164   fMemReader = new AliRawReaderMemory;
165   fClusterizer->SetReconstructor(fReconstructor);
166   fClusterizer->SetUseLabels(kFALSE);
167
168   if(fReconstructor->IsProcessingTracklets())
169     fOutputConst = fClusterizer->GetTrMemBlockSize();
170   return 0;
171 }
172
173 int AliHLTTRDClusterizerComponent::DoDeinit()
174 {
175   // Deinitialization of the component
176   delete fMemReader;
177   fMemReader = 0;
178   delete fClusterizer;
179   fClusterizer = 0;
180   
181   fReconstructor->SetClusters(0x0);
182   delete fReconstructor;
183   fReconstructor = 0x0;
184   return 0;
185
186   if (fRecoParam)
187     {
188       HLTDebug("Deleting fRecoParam");
189       delete fRecoParam;
190       fRecoParam = 0;
191     }
192 }
193
194 int AliHLTTRDClusterizerComponent::DoEvent( const AliHLTComponentEventData& evtData, 
195                                             const AliHLTComponentBlockData* blocks, 
196                                             AliHLTComponent_TriggerData& /*trigData*/, 
197                                             AliHLTUInt8_t* outputPtr, 
198                                             AliHLTUInt32_t& size, 
199                                             vector<AliHLTComponent_BlockData>& outputBlocks )
200 {
201   // Process an event
202
203   if (evtData.fEventID == 1)
204     CALLGRIND_START_INSTRUMENTATION;
205
206   HLTDebug( "NofBlocks %i", evtData.fBlockCnt );
207   // Process an event
208   AliHLTUInt32_t totalSize = 0, offset = 0;
209
210   //implement a usage of the following
211   //   AliHLTUInt32_t triggerDataStructSize = trigData.fStructSize;
212   //   AliHLTUInt32_t triggerDataSize = trigData.fDataSize;
213   //   void *triggerData = trigData.fData;
214   //HLTDebug( "Trigger data received. Struct size %d Data size %d Data location 0x%x", trigData.fStructSize, trigData.fDataSize, (UInt_t*)trigData.fData);
215
216   // Loop over all input blocks in the event
217   AliHLTComponentDataType expectedDataType = (kAliHLTDataTypeDDLRaw | kAliHLTDataOriginTRD);
218   for ( UInt_t iBlock = 0; iBlock < evtData.fBlockCnt; iBlock++ )
219     {      
220       const AliHLTComponentBlockData &block = blocks[iBlock];
221       // lets not use the internal TRD data types here : AliHLTTRDDefinitions::fgkDDLRawDataType
222       // which is depreciated - we use HLT global defs instead
223       //      if ( block.fDataType != (kAliHLTDataTypeDDLRaw | kAliHLTDataOriginTRD) )
224       AliHLTComponentDataType inputDataType = block.fDataType;
225       if ( inputDataType != expectedDataType)
226         {
227           HLTDebug( "Block # %i/%i; Event 0x%08LX (%Lu) Wrong received datatype: %s - required datatype: %s; Skipping",
228                     iBlock, evtData.fBlockCnt,
229                     evtData.fEventID, evtData.fEventID, 
230                     DataType2Text(inputDataType).c_str(), 
231                     DataType2Text(expectedDataType).c_str());
232           continue;
233         }
234       else 
235         {
236           HLTDebug("We get the right data type: Block # %i/%i; Event 0x%08LX (%Lu) Received datatype: %s; Block Size: %i",
237                    iBlock, evtData.fBlockCnt,
238                    evtData.fEventID, evtData.fEventID, 
239                    DataType2Text(inputDataType).c_str(),
240                    block.fSize);
241         }
242       
243       //      fMemReader->Reset();
244       fMemReader->SetMemory((UChar_t*) block.fPtr, block.fSize);
245
246       AliHLTUInt32_t spec = block.fSpecification;
247       
248       Int_t id = 1024;
249       
250       for ( Int_t ii = 0; ii < 18 ; ii++ ) {
251         if ( spec & 0x1 ) {
252           id += ii;
253           break;
254         }
255         spec = spec >> 1 ;
256       }
257
258       fMemReader->SetEquipmentID( id ); 
259       
260       fClusterizer->SetMemBlock(outputPtr+offset);
261       Bool_t iclustered = fClusterizer->Raw2ClustersChamber(fMemReader);
262       if (iclustered == kTRUE)
263         {
264           HLTDebug( "Clustered successfully");
265         }
266       else
267         {
268           HLTError("Clustering ERROR");
269           return -1;
270         }
271
272       // put the tree into output
273       //fcTree->Print();
274       
275       AliHLTUInt32_t addedSize;
276       if(fReconstructor->IsProcessingTracklets()){
277         addedSize = fClusterizer->GetAddedTrSize();
278         totalSize += fClusterizer->GetTrMemBlockSize();  //if IsProcessingTracklets() is enabled we always reserve a data block of size GetTrMemBlockSize() for the tracklets
279         if (addedSize > 0){
280           // Using low-level interface 
281           // with interface classes
282           if ( totalSize > size )
283             {
284               HLTError("Too much data; Data written over allowed buffer. Amount written: %lu, allowed amount: %lu.",
285                        totalSize, size );
286               return EMSGSIZE;
287             }
288
289           // Fill block 
290           AliHLTComponentBlockData bd;
291           FillBlockData( bd );
292           bd.fOffset = offset;
293           bd.fSize = addedSize;
294           //bd.fSpecification = spec;
295           bd.fSpecification = gkAliEventTypeData;
296           bd.fDataType = AliHLTTRDDefinitions::fgkMCMtrackletDataType;
297           outputBlocks.push_back( bd );
298           HLTDebug( "BD fPtr 0x%x, fOffset %i, size %i, dataType %s, spec 0x%x ", bd.fPtr, bd.fOffset, bd.fSize, DataType2Text(bd.fDataType).c_str(), spec);
299         }
300         offset = totalSize;
301       }
302
303       addedSize = fClusterizer->GetAddedClSize();
304       if (addedSize > 0){
305         // Using low-level interface 
306         // with interface classes
307         totalSize += addedSize;
308         if ( totalSize > size )
309           {
310             HLTError("Too much data; Data written over allowed buffer. Amount written: %lu, allowed amount: %lu.",
311                      totalSize, size );
312             return EMSGSIZE;
313           }
314                 
315         // Fill block 
316         AliHLTComponentBlockData bd;
317         FillBlockData( bd );
318         bd.fOffset = offset;
319         bd.fSize = addedSize;
320         //bd.fSpecification = spec;
321         bd.fSpecification = gkAliEventTypeData;
322         bd.fDataType = AliHLTTRDDefinitions::fgkClusterDataType;
323         outputBlocks.push_back( bd );
324         HLTDebug( "BD fPtr 0x%x, fOffset %i, size %i, dataType %s, spec 0x%x ", bd.fPtr, bd.fOffset, bd.fSize, DataType2Text(bd.fDataType).c_str(), spec);
325         offset = totalSize;
326               
327       }
328       else 
329         HLTWarning("Array of clusters is empty!");
330     }
331   fReconstructor->SetClusters(0x0);
332
333   size = totalSize;
334   HLTDebug("Event is done. size written to the output is %i", size);
335   return 0;
336 }
337
338 void AliHLTTRDClusterizerComponent::PrintObject( TClonesArray* inClustersArray)
339 {
340   AliTRDcluster* cluster=0x0;
341   
342   for (Int_t i=0; i < inClustersArray->GetEntriesFast(); i++){
343     cluster = dynamic_cast<AliTRDcluster*>(inClustersArray->At(i));
344     HLTDebug("cluster[%i]",i);
345     HLTDebug("  PadCol = %i; PadRow = %i; PadTime = %i", cluster->GetPadCol(), cluster->GetPadRow(), cluster->GetPadTime());
346     HLTDebug("  Detector = %i, Amplitude = %f, Center = %f", cluster->GetDetector(), cluster->GetQ(), cluster->GetCenter());
347     HLTDebug("  LocalTimeBin =  %i; NPads = %i; maskedPosition: %s, status: %s", cluster->GetLocalTimeBin(), cluster->GetNPads(),cluster->GetPadMaskedPosition(),cluster->GetPadMaskedPosition());
348   }
349   
350 }
351
352 int AliHLTTRDClusterizerComponent::Configure(const char* arguments){
353   int iResult=0;
354   if (!arguments) return iResult;
355   
356   TString allArgs=arguments;
357   TString argument;
358   int bMissingParam=0;
359
360   TObjArray* pTokens=allArgs.Tokenize(" ");
361   if (pTokens) {
362     for (int i=0; i<pTokens->GetEntries() && iResult>=0; i++) {
363       argument=((TObjString*)pTokens->At(i))->GetString();
364       if (argument.IsNull()) continue;
365       
366       if (argument.CompareTo("-OFFLINE")==0) {
367         fOfflineMode = kTRUE;
368         HLTFatal("You have selected OFFLINE mode!");
369         HLTFatal("This program shall NOT run on the HLT cluster like this!");
370         continue;
371       }
372       else if (argument.CompareTo("output_percentage")==0) {
373         if ((bMissingParam=(++i>=pTokens->GetEntries()))) break;
374         HLTInfo("Setting output percentage to: %s", ((TObjString*)pTokens->At(i))->GetString().Data());
375         fOutputPercentage=((TObjString*)pTokens->At(i))->GetString().Atoi();
376         continue;
377       } 
378       else if (argument.CompareTo("-geometry")==0) {
379         if ((bMissingParam=(++i>=pTokens->GetEntries()))) break;
380         HLTInfo("Setting geometry to: %s", ((TObjString*)pTokens->At(i))->GetString().Data());
381         fgeometryFileName=((TObjString*)pTokens->At(i))->GetString();
382         continue;
383       } 
384       if (argument.CompareTo("-lowflux")==0) {
385         fRecoParamType = 0;
386         HLTInfo("Low flux reconstruction selected");
387         continue;
388       }
389       if (argument.CompareTo("-highflux")==0) {
390         fRecoParamType = 1;
391         HLTInfo("High flux reconstruction selected");
392         continue;
393       }
394       if (argument.CompareTo("-cosmics")==0) {
395         fRecoParamType = 2;
396         HLTInfo("Cosmics reconstruction selected");
397         continue;
398       }
399       if (argument.CompareTo("-simulation")==0) {
400         fRecoDataType = 0;
401         HLTInfo("Awaiting simulated data");
402         continue;
403       }
404       if (argument.CompareTo("-experiment")==0) {
405         fRecoDataType = 1;
406         HLTInfo("Awaiting real data");
407         continue;
408       }
409       if (argument.CompareTo("-processTracklets")==0) {
410         fProcessTracklets = kTRUE;
411         HLTInfo("Processing L1 Tracklets");
412         continue;
413       }
414       if (argument.CompareTo("-noZS")==0) {
415         fOutputPercentage = 100;
416         HLTInfo("Awaiting non zero surpressed data");
417         continue;
418       }
419       if (argument.CompareTo("-faststreamer")==0) {
420         fHLTstreamer = kTRUE;
421         HLTInfo("Useing fast raw streamer");
422         continue;
423       }
424       else if (argument.CompareTo("-rawver")==0) {
425         if ((bMissingParam=(++i>=pTokens->GetEntries()))) break;
426         HLTInfo("Raw data version is: %s", ((TObjString*)pTokens->At(i))->GetString().Data());
427         fRawDataVersion=((TObjString*)pTokens->At(i))->GetString().Atoi();
428         continue;
429       } 
430       else if (argument.CompareTo("-yPosMethod")==0) {
431         if ((bMissingParam=(++i>=pTokens->GetEntries()))) break;
432         TString toCompareTo=((TObjString*)pTokens->At(i))->GetString();
433         if (toCompareTo.CompareTo("COG")==0){
434           HLTInfo("Setting yPosMethod method to: %s", toCompareTo.Data());
435           fyPosMethod=0;
436         }
437         else if (toCompareTo.CompareTo("LUT")==0){
438           HLTInfo("Setting yPosMethod method to: %s", toCompareTo.Data());
439           fyPosMethod=1;
440         }
441         else if (toCompareTo.CompareTo("Gauss")==0){
442           HLTInfo("Setting yPosMethod method to: %s", toCompareTo.Data());
443           fyPosMethod=2;
444         }
445         else {
446           HLTError("unknown argument for yPosMethod: %s", toCompareTo.Data());
447           iResult=-EINVAL;
448           break;
449         }
450         continue;
451       } 
452       
453       else {
454         HLTError("unknown argument: %s", argument.Data());
455         iResult=-EINVAL;
456         break;
457       }
458     }
459     delete pTokens;
460   }
461   if (bMissingParam) {
462     HLTError("missing parameter for argument %s", argument.Data());
463     iResult=-EINVAL;
464   }
465   if(iResult>=0){
466     if(fOfflineMode)SetOfflineParams();
467     iResult=SetParams();
468   }
469   return iResult;
470 }
471
472 int AliHLTTRDClusterizerComponent::SetParams()
473 {
474   Int_t iResult=0;
475   if(!AliCDBManager::Instance()->IsDefaultStorageSet()){
476     HLTError("DefaultStorage is not Set in CDBManager");
477     return -EINVAL;
478   }
479   if(AliCDBManager::Instance()->GetRun()<0){
480     HLTError("Run Number is not set in CDBManager");
481     return -EINVAL;
482   }
483   HLTInfo("CDB default storage: %s; RunNo: %i", (AliCDBManager::Instance()->GetDefaultStorage()->GetBaseFolder()).Data(), AliCDBManager::Instance()->GetRun());
484
485   if(!AliGeomManager::GetGeometry()){
486     if(!TFile::Open(fgeometryFileName.Data())){
487       HLTInfo("Loading standard geometry file");
488       AliGeomManager::LoadGeometry();
489     }else{
490       HLTWarning("Loading NON-standard geometry file");
491       AliGeomManager::LoadGeometry(fgeometryFileName.Data());
492     }
493     if(!AliGeomManager::GetGeometry()){
494       HLTError("Cannot load geometry");
495       return -EINVAL;
496     }
497   }
498   else{
499     HLTInfo("Geometry Already Loaded!");
500   }
501
502   TString recoOptions="hlt,!cw,sl_cf_0";
503
504   switch(fRecoDataType){
505   case 0: recoOptions += ",tc"; break;
506   case 1: recoOptions += ",!tc"; break;
507   }
508   switch(fyPosMethod){
509   case 0: recoOptions += ",!gs,!lut"; break;
510   case 1: recoOptions += ",!gs,lut"; break;
511   case 2: recoOptions += ",gs,!lut"; break;
512   }
513   if(fProcessTracklets) recoOptions += ",tp";
514   else  recoOptions += ",!tp";
515
516
517   if (fRecoParamType == 0)
518     {
519       HLTDebug("Low flux params init.");
520       fRecoParam = AliTRDrecoParam::GetLowFluxParam();
521     }
522
523   if (fRecoParamType == 1)
524     {
525       HLTDebug("High flux params init.");
526       fRecoParam = AliTRDrecoParam::GetHighFluxParam();
527     }
528   
529   if (fRecoParamType == 2)
530     {
531       HLTDebug("Cosmic Test params init.");
532       fRecoParam = AliTRDrecoParam::GetCosmicTestParam();
533     }
534
535   if (fRecoParam == 0)
536     {
537       HLTError("No reco params initialized. Sniffing big trouble!");
538       return -EINVAL;
539     }
540
541   fReconstructor->SetRecoParam(fRecoParam);
542   fReconstructor->SetStreamLevel(0, AliTRDReconstructor::kClusterizer);
543
544   HLTDebug("Reconstructor options are: %s",recoOptions.Data());
545   fReconstructor->SetOption(recoOptions.Data());
546
547   if (fRecoDataType < 0 || fRecoDataType > 1)
548     {
549       HLTWarning("No data type selected. Use -simulation or -experiment flag. Defaulting to simulation.");
550       fRecoDataType = 0;
551     }
552
553   if (fRecoDataType == 0)
554     {
555       AliTRDrawStreamBase::SetRawStreamVersion(AliTRDrawStreamBase::kTRDsimStream);
556       HLTDebug("Data type expected is SIMULATION!");
557     }
558
559   if (fRecoDataType == 1)
560     {
561       AliTRDrawStreamBase::SetRawStreamVersion(AliTRDrawStreamBase::kTRDrealStream);
562       HLTDebug("Data type expected is EXPERIMENT!");
563     }
564
565   if (fHLTstreamer)
566     {
567       AliTRDrawStreamBase::SetRawStreamVersion("FAST");
568       HLTDebug("fast rawstreamer used");  
569     }
570
571   if(!fClusterizer){
572     fClusterizer = new AliHLTTRDClusterizer("TRDCclusterizer", "TRDCclusterizer");  
573     HLTDebug("TRDClusterizer at 0x%x", fClusterizer);
574   }
575
576   fClusterizer->SetRawVersion(fRawDataVersion);
577
578   return iResult;
579 }
580
581 void AliHLTTRDClusterizerComponent::SetOfflineParams(){
582   if(!AliCDBManager::Instance()->IsDefaultStorageSet()){
583     HLTFatal("You are resetting the Default Storage of the CDBManager!");
584     HLTFatal("Let's hope that this program is NOT running on the HLT cluster!");
585     //AliCDBManager::Instance()->SetDefaultStorage("local://$ALICE_ROOT/OCDB");
586   }else{
587     HLTError("DefaultStorage was already set!");
588   }
589   if(AliCDBManager::Instance()->GetRun()<0){
590     HLTFatal("You are resetting the CDB run number to 0!");
591     HLTFatal("Let's hope that this program is NOT running on the HLT cluster!");
592     //AliCDBManager::Instance()->SetRun(0);
593   }else{
594     HLTError("Run Number was already set!");
595   }
596 }
597
598 int AliHLTTRDClusterizerComponent::Reconfigure(const char* cdbEntry, const char* chainId)
599 {
600   // see header file for class documentation
601
602   int iResult=0;
603   const char* path="HLT/ConfigTRD/ClusterizerComponent";
604   const char* defaultNotify="";
605   if (cdbEntry) {
606     path=cdbEntry;
607     defaultNotify=" (default)";
608   }
609   if (path) {
610     HLTInfo("reconfigure from entry %s%s, chain id %s", path, defaultNotify,(chainId!=NULL && chainId[0]!=0)?chainId:"<none>");
611     AliCDBEntry *pEntry = AliCDBManager::Instance()->Get(path/*,GetRunNo()*/);
612     if (pEntry) {
613       TObjString* pString=dynamic_cast<TObjString*>(pEntry->GetObject());
614       if (pString) {
615         HLTInfo("received configuration object string: \'%s\'", pString->GetString().Data());
616         iResult=Configure(pString->GetString().Data());
617       } else {
618         HLTError("configuration object \"%s\" has wrong type, required TObjString", path);
619       }
620     } else {
621       HLTError("cannot fetch object \"%s\" from CDB", path);
622     }
623   }
624
625   return iResult;
626 }