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