SDD extrusions eliminated (M. Sitta)
[u/mrichter/AliRoot.git] / ITS / ITSSPDPHYSda.cxx
CommitLineData
803e6db5 1/*
2Contact: henrik.tydesjo@cern.ch
3Link: tydes.home.cern.ch/tydes/doc/CalibrationOverview/CalibrationAlgorithms/
4Run Type: PHYSICS
5DA Type: MON
6Number of events needed: Depending on muliplicity per event
7Input Files: spd_physics_params , ./calibResults/DeadReferenceTmp/* , ./calibResults/DeadToFXS/*
8Output Files: ./calibResults/NoisyReference/* , ./calibResults/DeadReference/* , ./calibResults/NoisyToFXS/* , ./calibResults/DeadReferenceTmp/*,./calibResults/DeadToFXS/*
9Trigger types used: PHYSICS
10*/
11
12////////////////////////////////////////////////////////////////////////////////
13// This program can be compiled in two modes. //
14// //
15// 1. Online. With the DAQ DA framework. This is the default operating mode. //
16// //
17// 2. Offline. Without the DAQ DA framework. Define the SPD_DA_OFF //
18// environment var. Call this program with the name of the executable //
19// followed by the runNr and the data files to process. //
20// //
21////////////////////////////////////////////////////////////////////////////////
22
23#ifndef SPD_DA_OFF
24extern "C" {
25#include "daqDA.h"
26}
27#endif
28#include "event.h"
29#include "monitor.h"
30#include "AliRawReaderDate.h"
31#include "AliITSRawStreamSPD.h"
32#include "AliITSOnlineSPDphys.h"
33#include "AliITSOnlineSPDphysAnalyzer.h"
34#include "AliITSOnlineCalibrationSPDhandler.h"
35#include "AliLog.h"
36#include <iostream>
37#include <fstream>
38#include <TROOT.h>
39#include <TPluginManager.h>
40#include <TObjArray.h>
41#include <TString.h>
42
43int main(int argc, char **argv) {
44 if (argc<2) {
45 printf("Wrong number of arguments\n");
46 return -1;
47 }
48
49 // directory structure, hard coded
50 char *saveDirDead = "./calibResults/Dead"; // may NOT delete content
51 char *saveDirDeadToFXS = "./calibResults/DeadToFXS"; // may delete content
52 char *saveDirDeadRef = "./calibResults/DeadReference"; // may delete content
53 char *saveDirDeadRefTmp = "./calibResults/DeadReferenceTmp"; // may NOT delete content
54 char *saveDirNoisyToFXS = "./calibResults/NoisyToFXS"; // may delete content
55 char *saveDirNoisyRef = "./calibResults/NoisyReference"; // may delete content
56 char *saveDirIdsToFXS = "./calibResults/IdsToFXS"; // may delete content
57 char *configFilesDir = "./configFiles"; // may delete content
58 // make sure the directory structure is put up correctly:
59 system("mkdir ./calibResults >& /dev/null");
60 system("mkdir ./calibResults/Dead >& /dev/null");
61 system("mkdir ./calibResults/DeadToFXS >& /dev/null");
62 system("mkdir ./calibResults/DeadReference >& /dev/null");
63 system("mkdir ./calibResults/DeadReferenceTmp >& /dev/null");
64 system("mkdir ./calibResults/NoisyToFXS >& /dev/null");
65 system("mkdir ./calibResults/NoisyReference >& /dev/null");
66 system("mkdir ./calibResults/IdsToFXS >& /dev/null");
67 system("mkdir ./configFiles >& /dev/null");
68 // parameters config file
69 TString paramsFileName = Form("%s/physics_params.txt",configFilesDir);
70
71 // This line is needed in case of a stand-alone application w/o
72 // $ROOTSYS/etc/system.rootrc file
73 gROOT->GetPluginManager()->AddHandler("TVirtualStreamerInfo",
74 "*",
75 "TStreamerInfo",
76 "RIO",
77 "TStreamerInfo()");
78
79 // turn off annoying warning messages
80 new AliLog;
81 AliLog::Instance()->SetGlobalDebugLevel(-20);
82
83
84 // ********* STEP 0: Get configuration files from db (if there are any) , then read parameters*********
85 UInt_t nrTuningParams = 0;
86 TObjArray paramNames; paramNames.SetOwner(kTRUE);
87 TObjArray paramVals; paramVals.SetOwner(kTRUE);
88
89 // tuning parameters:
90 Int_t par_status = 0;
91#ifndef SPD_DA_OFF
92 TString idp = "spd_physics_params";
93 par_status=daqDA_DB_getFile(idp.Data(),paramsFileName.Data());
94 if (par_status) {
95 printf("Failed to get config file %s: status=%d. Using default tuning parameters.\n",idp.Data(),par_status);
96 }
97#endif
98 if (par_status==0) {
99 ifstream paramsFile;
100 paramsFile.open(paramsFileName.Data(), ifstream::in);
101 if (paramsFile.fail()) {
102 printf("No config file (%s) present. Using default tuning parameters.\n",paramsFileName.Data());
103 }
104 else {
105 while(1) {
106 Char_t paramN[50];
107 Char_t paramV[50];
108 paramsFile >> paramN;
109 if (paramsFile.eof()) break;
110 paramsFile >> paramV;
111 TString* paramNS = new TString(paramN);
112 TString* paramVS = new TString(paramV);
113 paramNames.AddAtAndExpand((TObject*)paramNS,nrTuningParams);
114 paramVals.AddAtAndExpand((TObject*)paramVS,nrTuningParams);
115 nrTuningParams++;
116 if (paramsFile.eof()) break;
117 }
118 paramsFile.close();
119 }
120 }
121 // for (UInt_t i=0; i<nrTuningParams; i++) {
122 // printf("Entry %d: N=%s , V=%s\n",i,((TString*)paramNames.At(i))->Data(),((TString*)paramVals.At(i))->Data());
123 // }
124
125
126
127
128
129 // ********* STEP 1: Produce phys container files (Reference Data). ***********************************
130
131#ifndef SPD_DA_OFF
132 if (getenv("DATE_RUN_NUMBER")==0) {
133 printf("DATE_RUN_NUMBER not properly set.\n");
134 return -1;
135 }
136 int runNr = atoi(getenv("DATE_RUN_NUMBER"));
137#else
138 int runNr = atoi(argv[1]);
139 int startSeg = 2;
140#endif
141
142
143 // container objects
144 AliITSOnlineSPDphys *physObj[20];
145 Bool_t bPhysInit[20];
146 for (UInt_t eqId=0; eqId<20; eqId++) {
147 physObj[eqId]=NULL;
148 bPhysInit[eqId]=kFALSE;
149 }
150
151
152 // loop over run segments in case of offline mode
153#ifdef SPD_DA_OFF
154 for (int segNr=startSeg; segNr<argc; segNr++) {
155#endif
156
157 int status;
158
159 /* define data source : */
160#ifndef SPD_DA_OFF
161 status=monitorSetDataSource( argv[1] ); // should be "^SPD" in order to get full detector online
162#else
163 status=monitorSetDataSource( argv[segNr] );
164#endif
165 if (status!=0) {
166 printf("monitorSetDataSource() failed : %s\n",monitorDecodeError(status));
167 return -1;
168 }
169 /* declare monitoring program */
170 status=monitorDeclareMp("ITS_SPD_PHYS");
171 if (status!=0) {
172 printf("monitorDeclareMp() failed : %s\n",monitorDecodeError(status));
173 return -1;
174 }
175 /* define wait event timeout - 1s max */
176 monitorSetNowait();
177 monitorSetNoWaitNetworkTimeout(1000);
178
179
180 UInt_t eventNr=0;
181
182 /* main loop (infinite) */
183 for(;;) {
184
185 struct eventHeaderStruct *event;
186 eventTypeType eventT;
187
188 /* check shutdown condition */
189#ifndef SPD_DA_OFF
190 if (daqDA_checkShutdown()) {break;}
191#endif
192
193 /* get next event (blocking call until timeout) */
194 status=monitorGetEventDynamic((void **)&event);
195 if (status==MON_ERR_EOF) {
196 printf ("End of File detected\n");
197 break; /* end of monitoring file has been reached */
198 }
199
200 if (status!=0) {
201 printf("monitorGetEventDynamic() failed : %s\n",monitorDecodeError(status));
202 break;
203 }
204
205 /* retry if got no event */
206 if (event==NULL) {
207 continue;
208 }
209
210 eventT=event->eventType;
211 if (eventT == PHYSICS_EVENT){
212
213 eventNr++;
214 // printf("eventNr %d\n",eventNr);
215
216 AliRawReader *reader = new AliRawReaderDate((void*)event);
217 AliITSRawStreamSPD *str = new AliITSRawStreamSPD(reader);
218
219 // for (UInt_t eqId=0; eqId<20; eqId++) {
220 // reader->Reset();
221 // reader->Select("ITSSPD",eqId,eqId);
222
223 while (str->Next()) {
224
225 Int_t eqId = reader->GetDDLID();
226 if (eqId>=0 && eqId<20) {
227 if (!bPhysInit[eqId]) {
228 TString fileName = Form("%s/SPDphys_run_%d_eq_%d.root",saveDirNoisyRef,runNr,eqId);
229 physObj[eqId] = new AliITSOnlineSPDphys(fileName.Data());
230 physObj[eqId]->AddRunNr(runNr);
231 physObj[eqId]->SetEqNr(eqId);
232 bPhysInit[eqId]=kTRUE;
233 }
234
235 UInt_t hs = str->GetHalfStaveNr();
236 UInt_t chip = str->GetChipAddr();
237 physObj[eqId]->IncrementHits(hs,chip,str->GetChipCol(),str->GetChipRow());
238
239 }
240 }
241
242 for (UInt_t eqId=0; eqId<20; eqId++) {
243 if (bPhysInit[eqId]) {
244 physObj[eqId]->IncrementNrEvents();
245 }
246 }
247
248 // }
249
250 delete str;
251 delete reader;
252
253 }
254
255 /* free resources */
256 free(event);
257
258 }
259
260
261#ifdef SPD_DA_OFF
262 printf("progress: %d\n",(unsigned int)( ((Float_t)(segNr-startSeg+1))/(argc-startSeg)*50 ));
263 }
264#endif
265
266 // clean up phys objects (also saves them)
267 for (UInt_t eqId=0; eqId<20; eqId++) {
268 if (physObj[eqId]!=NULL) delete physObj[eqId];
269 }
270
271
272
273
274
275 // ********* STEP 2: Analyze phys container files. ************************************************
276
277 // clear noisyToFXS dir:
278 TString command;
279 command = Form("cd %s; rm -f *",saveDirNoisyToFXS);
280 system(command.Data());
281 // clear deadToFXS dir:
282 command = Form("cd %s; rm -f *",saveDirDeadToFXS);
283 system(command.Data());
284
285
286 // create calibration handler and read dead from previous calibrations
287 AliITSOnlineCalibrationSPDhandler* handler = new AliITSOnlineCalibrationSPDhandler();
288 handler->SetFileLocation(saveDirDead);
289 handler->ReadDeadFromFiles();
290
291
292 UInt_t firstRunNrDead = runNr;
293
294
295 UInt_t nrEnoughStatNoisy = 0;
296 UInt_t nrEqActiveNoisy = 0;
297 Bool_t eqActiveNoisy[20];
298
299 // *** *** *** start loop over equipments (eq_id)
300 for (UInt_t eqId=0; eqId<20; eqId++) {
301 eqActiveNoisy[eqId] = kFALSE;
302
303 // create analyzer for this eq
304 TString fileName = Form("%s/SPDphys_run_%d_eq_%d.root",saveDirNoisyRef,runNr,eqId);
305 AliITSOnlineSPDphysAnalyzer *noisyAnalyzer = new AliITSOnlineSPDphysAnalyzer(fileName.Data(),handler);
306
307 // check data in container
308 if (noisyAnalyzer->GetEqNr() != eqId) {
309 if (noisyAnalyzer->GetEqNr() != 999) {
310 printf("Error: Mismatching EqId in Container data and filename (%d!=%d). Skipping.\n",
311 noisyAnalyzer->GetEqNr(),eqId);
312 }
313 delete noisyAnalyzer;
314 continue;
315 }
316
317 nrEqActiveNoisy++;
318 eqActiveNoisy[eqId] = kTRUE;
319
320 // configure analyzer with tuning parameters etc:
321 for (UInt_t i=0; i<nrTuningParams; i++) {
322 noisyAnalyzer->SetParam(((TString*)paramNames.At(i))->Data(),((TString*)paramVals.At(i))->Data());
323 }
324
325 printf("SPD phys STEP 2: Noisy search for eq %d\n",eqId);
326
327 // search for noisy pixels:
328 nrEnoughStatNoisy += noisyAnalyzer->ProcessNoisyPixels();
329
330 // copy this phys obj to temporary dead reference dir to process after noisy search
331 TString fileNameDead = Form("%s/SPDphys_dead_run_0_0_eq_%d.root",saveDirDeadRefTmp,eqId);
332 AliITSOnlineSPDphys* physObj = new AliITSOnlineSPDphys(fileNameDead.Data());
333 physObj->AddPhys(noisyAnalyzer->GetOnlinePhys());
334 if (physObj->GetNrRuns()>0) {
335 UInt_t firstRunNr = physObj->GetRunNr(0);
336 if (firstRunNrDead>firstRunNr) {
337 firstRunNrDead=firstRunNr;
338 }
339 }
340 // remove noisy pixels from dead hitmap
341 for (UInt_t hs=0; hs<6; hs++) {
342 for (UInt_t chip=0; chip<10; chip++) {
343 for (UInt_t ind=0; ind<handler->GetNrNoisyC(eqId,hs,chip); ind++) {
344 UInt_t col = handler->GetNoisyColAtC(eqId,hs,chip,ind);
345 UInt_t row = handler->GetNoisyRowAtC(eqId,hs,chip,ind);
346 physObj->AddHits(hs,chip,col,row,-noisyAnalyzer->GetOnlinePhys()->GetHits(hs,chip,col,row));
347 }
348 }
349 }
350
351 delete physObj;
352 delete noisyAnalyzer;
353
354#ifndef SPD_DA_OFF
355 daqDA_progressReport((unsigned int)((eqId+1)*2.5));
356#else
357 printf("progress: %d\n",(unsigned int)(50+(eqId+1)*1.25));
358#endif
359 }
360 // *** *** *** end loop over equipments (eq_id)
361
362 printf("Noisy search finished. %d noisy pixels found. %d chips (%d) had enough statistics.\n",
363 handler->GetNrNoisy(),nrEnoughStatNoisy,nrEqActiveNoisy*60);
364 handler->SetFileLocation(saveDirNoisyToFXS);
365 handler->WriteNoisyToFiles();
366
367
368
369
370
371
372
373
374 UInt_t nrEnoughStatChips = 0;
375 UInt_t nrDeadChips = 0;
376 UInt_t nrInefficientChips = 0;
377 UInt_t nrEqActiveDead = 0;
378 Bool_t eqActiveDead[20];
379
380 // *** *** *** start loop over equipments (eq_id)
381 for (UInt_t eqId=0; eqId<20; eqId++) {
382 eqActiveDead[eqId] = kFALSE;
383
384 // setup analyzer for dead search
385 TString fileNameDead = Form("%s/SPDphys_dead_run_0_0_eq_%d.root",saveDirDeadRefTmp,eqId);
386 AliITSOnlineSPDphys* physObj = new AliITSOnlineSPDphys(fileNameDead.Data());
387 AliITSOnlineSPDphysAnalyzer* deadAnalyzer = new AliITSOnlineSPDphysAnalyzer(physObj,handler);
388 // check data in container
389 if (deadAnalyzer->GetEqNr() != eqId) {
390 if (deadAnalyzer->GetEqNr() != 999) {
391 printf("Error: Mismatching EqId in Dead Container data and filename (%d!=%d). Skipping.\n",
392 deadAnalyzer->GetEqNr(),eqId);
393 }
394 delete deadAnalyzer;
395 continue;
396 }
397
398 nrEqActiveDead++;
399 eqActiveDead[eqId] = kTRUE;
400
401 // configure analyzer with tuning parameters etc:
402 for (UInt_t i=0; i<nrTuningParams; i++) {
403 deadAnalyzer->SetParam(((TString*)paramNames.At(i))->Data(),((TString*)paramVals.At(i))->Data());
404 }
405
406 printf("SPD phys STEP 2: Dead search for eq %d\n",eqId);
407
408 // search for dead pixels:
409 nrEnoughStatChips += deadAnalyzer->ProcessDeadPixels();
410 nrDeadChips += deadAnalyzer->GetNrDeadChips();
411 nrInefficientChips += deadAnalyzer->GetNrInefficientChips();
412
413 delete deadAnalyzer;
414
415#ifndef SPD_DA_OFF
416 daqDA_progressReport((unsigned int)(50+(eqId+1)*2.5));
417#else
418 printf("progress: %d\n",(unsigned int)(75+(eqId+1)*1.25));
419#endif
420 }
421 // *** *** *** end loop over equipments (eq_id)
422
423
424 printf("Dead search finished. %d dead pixels in total.\n%d chips (%d) had enough statistics. %d chips were dead. %d chips were inefficient.\n",handler->GetNrDead(),nrEnoughStatChips,nrEqActiveDead*60,nrDeadChips,nrInefficientChips);
425 handler->SetFileLocation(saveDirDead);
426 handler->WriteDeadToFilesAlways();
427
428 handler->SetFileLocation(saveDirDeadToFXS);
429 handler->WriteDeadToFilesAlways();
430// *** old code (used if not all dead data should be uploaded)
431// UInt_t nrDeadFilesToTar = 0;
432// handler->SetFileLocation(saveDirDeadToFXS);
433// for (UInt_t eqId=0; eqId<20; eqId++) {
434// if (eqActiveDead[eqId]) {
435// handler->WriteDeadToFile(eqId);
436// nrDeadFilesToTar++;
437// }
438// }
439//***
440
441 printf("Opening id list file\n");
442 TString idsFXSFileName = Form("%s/FXSids_run_%d.txt",saveDirIdsToFXS,runNr);
443 ofstream idsFXSfile;
444 idsFXSfile.open(idsFXSFileName.Data());
445
446
447 // if there is no chip in category "needsMoreStat"
448 if (nrEnoughStatChips+nrDeadChips+nrInefficientChips == nrEqActiveDead*60) {
449 // calibration is complete
450 printf("Dead calibration is complete.\n");
451
452
453
454 printf("Preparing dead reference data\n");
455 // send reference data for dead pixels to FXS
456 TString tarFiles = "";
457 for (UInt_t eqId=0; eqId<20; eqId++) {
458 if (eqActiveDead[eqId]) {
459 printf("Preparing dead pixels for eq %d\n",eqId);
460 // move file to ref dir
461 TString fileName = Form("%s/SPDphys_dead_run_0_0_eq_%d.root",saveDirDeadRefTmp,eqId);
462 TString newFileName = Form("%s/SPDphys_dead_run_%d_%d_eq_%d.root",saveDirDeadRef,firstRunNrDead,runNr,eqId);
463 TString command = Form("mv -f %s %s",fileName.Data(),newFileName.Data());
464 system(command.Data());
465
466 tarFiles.Append(Form("SPDphys_dead_run_%d_%d_eq_%d.root ",firstRunNrDead,runNr,eqId));
467 }
468 }
469 TString send_command = Form("cd %s; tar -cf ref_phys_dead.tar %s",saveDirDeadRef,tarFiles.Data());
470 system(send_command.Data());
471 TString fileName = Form("%s/ref_phys_dead.tar",saveDirDeadRef);
472 TString id = "SPD_ref_phys_dead";
473#ifndef SPD_DA_OFF
474 status = daqDA_FES_storeFile(fileName.Data(),id.Data());
475 if (status!=0) {
476 printf("Failed to export file %s , status %d\n",fileName.Data(),status);
477 return -1;
478 }
479#endif
480 idsFXSfile << Form("%s\n",id.Data());
481// for (UInt_t eqId=0; eqId<20; eqId++) { // OLD CODE NOT TARED
482// if (eqActiveDead[eqId]) {
483// TString fileName = Form("%s/SPDphys_dead_run_0_0_eq_%d.root",saveDirDeadRefTmp,eqId);
484// // move file to ref dir
485// TString newFileName = Form("%s/SPDphys_dead_run_%d_%d_eq_%d.root",saveDirDeadRef,firstRunNrDead,runNr,eqId);
486// TString command = Form("mv -f %s %s",fileName.Data(),newFileName.Data());
487// system(command.Data());
488// // send ref data to FXS
489// TString id = Form("SPD_ref_phys_dead_%d",eqId);
490//#ifndef SPD_DA_OFF
491// Int_t status = daqDA_FES_storeFile(newFileName.Data(),id.Data());
492// if (status!=0) {
493// printf("Failed to export file %s , status %d\n",newFileName.Data(),status);
494// return -1;
495// }
496//#endif
497// idsFXSfile << Form("%s\n",id.Data());
498// }
499// else {
500// TString command = Form("rm -f %s/SPDphys_dead_run_0_0_eq_%d.root",saveDirDeadRefTmp,eqId);
501// system(command.Data());
502// }
503// }
504 }
505
506
507 printf("Preparing noisy reference data\n");
508 // send reference data for this run to FXS
509 TString tarFiles = "";
510 for (UInt_t eqId=0; eqId<20; eqId++) {
511 if (eqActiveNoisy[eqId]) {
512 tarFiles.Append(Form("SPDphys_run_%d_eq_%d.root ",runNr,eqId));
513 }
514 }
515 TString send_command = Form("cd %s; tar -cf ref_phys.tar %s",saveDirNoisyRef,tarFiles.Data());
516 system(send_command.Data());
517 TString fileName = Form("%s/ref_phys.tar",saveDirNoisyRef);
518 TString id = "SPD_ref_phys";
519#ifndef SPD_DA_OFF
520 status = daqDA_FES_storeFile(fileName.Data(),id.Data());
521 if (status!=0) {
522 printf("Failed to export file %s , status %d\n",fileName.Data(),status);
523 return -1;
524 }
525#endif
526 idsFXSfile << Form("%s\n",id.Data());
527
528
529// // send reference data for this run to FXS - OLD CODE NOT TARED
530// for (UInt_t eqId=0; eqId<20; eqId++) {
531// if (eqActiveNoisy[eqId]) {
532// TString fileName = Form("%s/SPDphys_run_%d_eq_%d.root",saveDirNoisyRef,runNr,eqId);
533// TString id = Form("SPD_ref_phys_%d",eqId);
534//#ifndef SPD_DA_OFF
535// Int_t status = daqDA_FES_storeFile(fileName.Data(),id.Data());
536// if (status!=0) {
537// printf("Failed to export file %s , status %d\n",fileName.Data(),status);
538// return -1;
539// }
540// idsFXSfile << Form("%s\n",id.Data());
541// }
542// }
543//#endif
544
545
546
547
548 printf("Preparing dead files\n");
549 // send dead pixels to FXS
550 // if (nrDeadFilesToTar>0) { //*** old code (used if not all dead data should be uploaded)
551 // send a tared file of all the dead files
552 send_command = Form("cd %s; tar -cf dead_phys.tar *",saveDirDeadToFXS);
553 // printf("\n\n%s\n\n",command.Data());
554 system(send_command.Data());
555 fileName = Form("%s/dead_phys.tar",saveDirDeadToFXS);
556 id = "SPD_phys_dead";
557#ifndef SPD_DA_OFF
558 Int_t send_status = daqDA_FES_storeFile(fileName.Data(),id.Data());
559 if (send_status!=0) {
560 printf("Failed to export file %s , status %d\n",fileName.Data(),send_status);
561 return -1;
562 }
563#endif
564 idsFXSfile << Form("%s\n",id.Data());
565 // } //*** old code (used if not all dead data should be uploaded)
566
567
568 // send noisy pixels to FXS
569 if (handler->GetNrNoisy()>0) { // there must be at least one file created
570 printf("Preparing noisy files\n");
571 // send a tared file of all the noisy files
572 TString command = Form("cd %s; tar -cf noisy_phys.tar *",saveDirNoisyToFXS);
573 // printf("\n\n%s\n\n",command.Data());
574 system(command.Data());
575 TString fileName = Form("%s/noisy_phys.tar",saveDirNoisyToFXS);
576 TString id = "SPD_phys_noisy";
577#ifndef SPD_DA_OFF
578 status = daqDA_FES_storeFile(fileName.Data(),id.Data());
579 if (status!=0) {
580 printf("Failed to export file %s , status %d\n",fileName.Data(),status);
581 return -1;
582 }
583#endif
584 idsFXSfile << Form("%s\n",id.Data());
585 }
586
587
588 // send ids file to FXS
589 idsFXSfile.close();
590 id = "SPD_id_list";
591#ifndef SPD_DA_OFF
592 status = daqDA_FES_storeFile(idsFXSFileName.Data(),id.Data());
593 if (status!=0) {
594 printf("Failed to export file %s , status %d\n",idsFXSFileName.Data(),status);
595 return -1;
596 }
597#endif
598
599
600
601
602 delete handler;
603
604
605 return 0;
606}