/[PAMELA software]/YodaProfiler/src/R2-D2.cpp
ViewVC logotype

Annotation of /YodaProfiler/src/R2-D2.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.3 - (hide annotations) (download)
Mon Nov 13 08:49:49 2006 UTC (18 years ago) by mocchiut
Branch: MAIN
CVS Tags: v2r04
Changes since 1.2: +42 -3 lines
Small bug in ResursTime method fixed

1 mocchiut 1.1 //
2     // C/C++ headers
3     //
4     #include <iostream>
5     #include <iomanip>
6     #include <fstream>
7     #include <sstream>
8     //
9     // ROOT headers
10     //
11     #include <TString.h>
12 mocchiut 1.2 #include <TTimeStamp.h>
13 mocchiut 1.1 #include <TSQLServer.h>
14     #include <TFile.h>
15     #include <TSystem.h>
16     //
17     // Detector's package headers
18     //
19     #include <GLTables.h>
20     //
21     using namespace std;
22     //
23     //
24     //
25     #include <YodaProfilerVerl2.h>
26     //
27     // Usage subroutine
28     //
29     void r2d2usage(){
30     printf("\nUsage:\n");
31     printf("\n R2-D2 [-h | --help] [--version] [-idRun ID_RUN] [-filename filename]\n");
32     printf("\n [-host host] [-user username] [-psw password] \n");
33     printf("\n --version print informations about compilation and exit\n");
34     printf("\n -h | --help print this help and exit \n");
35     printf("\n -v | --verbose be verbose [default: print nothing on STDOUT]\n");
36     printf("\n -idRun run ID_RUN: ID number of the run \n");
37     printf("\n -filename file output yoda filename \n");
38     printf("\n -host name for the host [default = $PAM_DBHOST or mysql://localhost/pamelaprod]\n");
39     printf("\n -user username for the DB [default = $PAM_DBUSER or \"anonymous\"] \n");
40     printf("\n -psw password for the DB [default = $PAM_DBPSW or \"\"]\n");
41     printf("\n -tzone timezone the time zone: UTC,GMT,MSK,MSD,CET,CEST are accepted \n");
42     printf("\n -convert dbtime convert the dbtime given in seconds (from the DB) to a string\n");
43     printf("\n -runat date returns run number which contains the given date,\n");
44     printf("\n for date use the SQL format \"yyyy-mm-dd hh:mm:ss\" \n");
45     printf("\n -runatDB time returns run number which contains the given DB time\n");
46     printf("\n -tsfile file yoda filename for the time sync (to be used with -obt)\n");
47     printf("\n -obt OBT OBT in ms returns a date (to be used with -tsfile)\n");
48 mocchiut 1.3 printf("\n -getRTime OBT OBT in ms returns Resurs time (to be used with -tsfile)\n");
49 mocchiut 1.1 printf("\n -dumpTLEfor date save into file tle.txt the TLE for the given date,\n");
50     printf("\n for date use the SQL format \"yyyy-mm-dd hh:mm:ss\" \n");
51     printf("\nExamples: \n");
52     printf("\n R2-D2 -idRun 1085 \n");
53     printf("\n R2-D2 -filename DW_050208_00900.root \n");
54     printf("\n R2-D2 -idRun 1085 -filename DW_050208_00900.root \n");
55     };
56     //
57     // Here the main
58     //
59     int main(int numinp, char *inps[]){
60     //
61     // Variables booking
62     //
63     TString message;
64     Int_t error = 0;
65     //
66     UInt_t run = 0ULL;
67     //
68     TString filename = "";
69     //
70     TSQLServer *dbc = 0;
71     TString host = "mysql://localhost/pamelaprod";
72     TString user = "anonymous";
73     TString psw = "";
74     //
75     const char *pamdbhost=gSystem->Getenv("PAM_DBHOST");
76     const char *pamdbuser=gSystem->Getenv("PAM_DBUSER");
77     const char *pamdbpsw=gSystem->Getenv("PAM_DBPSW");
78     if ( !pamdbhost ) pamdbhost = "";
79     if ( !pamdbuser ) pamdbuser = "";
80     if ( !pamdbpsw ) pamdbpsw = "";
81     if ( strcmp(pamdbhost,"") ) host = pamdbhost;
82     if ( strcmp(pamdbuser,"") ) user = pamdbuser;
83     if ( strcmp(pamdbpsw,"") ) psw = pamdbpsw;
84     //
85     // printf(" host %s user %s psw %s \n",host.Data(),user.Data(),psw.Data());
86     //
87     TString tzone = "UTC";
88     TString runtime = "1970-01-01 00:00:00";
89     TString tletime = "1970-01-01 00:00:00";
90     UInt_t dbti = 0;
91     Bool_t convert = false;
92 mocchiut 1.3 Bool_t convres = false;
93 mocchiut 1.1 Bool_t ruti = false;
94     Bool_t dtle = false;
95     Bool_t ruti2 = false;
96     Bool_t convobt = false;
97     Bool_t convobtts = false;
98     //
99     UInt_t runtime2 = 0;
100     UInt_t obt = 0;
101 mocchiut 1.3 UInt_t res = 0;
102 mocchiut 1.1 TString tsfile = "";
103     //
104     TSQLResult *pResult;
105     TSQLRow *Row;
106     int t;
107     int r;
108     stringstream myquery;
109     //
110     // Checking input parameters
111     //
112     Int_t i = 0;
113     if ( numinp > 1 ){
114     while ( i < numinp ){
115     if ( !strcmp(inps[i],"--version") ){
116     YodaProfilerInfo(true);
117     exit(0);
118     };
119     if ( !strcmp(inps[i],"-h") || !strcmp(inps[i],"--help") ){
120     r2d2usage();
121     exit(0);
122     };
123     if ( !strcmp(inps[i],"-idRun") ) {
124     if ( numinp-1 < i+1 ) {
125     r2d2usage();
126     exit(-3);
127     };
128     run = (UInt_t)atoll(inps[i+1]);
129     };
130     if ( !strcmp(inps[i],"-filename") ) {
131     if ( numinp-1 < i+1 ){
132     r2d2usage();
133     exit(-3);
134     };
135     filename = (TString)inps[i+1];
136     };
137     if ( !strcmp(inps[i],"-host") ) {
138     if ( numinp-1 < i+1 ){
139     r2d2usage();
140     exit(-3);
141     };
142     host = (TString)inps[i+1];
143     };
144     if ( !strcmp(inps[i],"-user") ) {
145     if ( numinp-1 < i+1 ){
146     r2d2usage();
147     exit(-3);
148     };
149     user = (TString)inps[i+1];
150     };
151     if ( !strcmp(inps[i],"-psw") ) {
152     if ( numinp-1 < i+1 ){
153     r2d2usage();
154     exit(-3);
155     };
156     psw = (TString)inps[i+1];
157     };
158     //
159     if ( !strcmp(inps[i],"-tsfile") ) {
160     convobtts = true;
161     if ( numinp-1 < i+1 ){
162     r2d2usage();
163     exit(-3);
164     };
165     tsfile = (TString)inps[i+1];
166     };
167     //
168     if ( !strcmp(inps[i],"-obt") ) {
169     convobt = true;
170     if ( numinp-1 < i+1 ){
171     r2d2usage();
172     exit(-3);
173     };
174     obt = (UInt_t)atoll(inps[i+1]);
175     };
176     //
177 mocchiut 1.3 if ( !strcmp(inps[i],"-getRTime") ) {
178     convres = true;
179     if ( numinp-1 < i+1 ){
180     r2d2usage();
181     exit(-3);
182     };
183     res = (UInt_t)atoll(inps[i+1]);
184     };
185     //
186 mocchiut 1.1 //
187     if ( !strcmp(inps[i],"-tzone") ) {
188     if ( numinp-1 < i+1 ){
189     r2d2usage();
190     exit(-3);
191     };
192     tzone = (TString)inps[i+1];
193     };
194     //
195     if ( !strcmp(inps[i],"-convert") ) {
196     convert = true;
197     if ( numinp-1 < i+1 ){
198     r2d2usage();
199     exit(-3);
200     };
201     dbti = (UInt_t)atoll(inps[i+1]);
202     };
203     //
204     if ( !strcmp(inps[i],"-runat") ) {
205     ruti = true;
206     if ( numinp-1 < i+1 ){
207     r2d2usage();
208     exit(-3);
209     };
210     runtime = (TString)inps[i+1];
211     };
212     //
213     if ( !strcmp(inps[i],"-dumpTLEfor") ) {
214     dtle = true;
215     if ( numinp-1 < i+1 ){
216     r2d2usage();
217     exit(-3);
218     };
219     tletime = (TString)inps[i+1];
220     };
221     //
222     //
223     if ( !strcmp(inps[i],"-runatDB") ) {
224     ruti2 = true;
225     if ( numinp-1 < i+1 ){
226     r2d2usage();
227     exit(-3);
228     };
229     runtime2 = (UInt_t)atoll(inps[i+1]);
230     };
231     //
232     i++;
233     };
234     //
235     } else {
236     //
237     // no input parameters exit with error, we need at least the run id.
238     //
239     r2d2usage();
240     exit(-2);
241     };
242     //
243     // Connect to the DB
244     //
245     dbc = TSQLServer::Connect(host.Data(),user.Data(),psw.Data());
246     if( !dbc ) throw -2;
247     //
248     bool connect = dbc->IsConnected();
249     //
250     if( !connect ){
251     printf(" Error, not connected to DB\n");
252     exit(-1);
253     };
254     //
255 mocchiut 1.2 myquery.str("");
256     myquery << "SET time_zone='+0:00'";
257     dbc->Query(myquery.str().c_str());
258     //
259 mocchiut 1.1 GL_ROOT *glroot = new GL_ROOT();
260     GL_RUN *glrun = new GL_RUN();
261     GL_TIMESYNC *dbtime = new GL_TIMESYNC();
262     //
263     // At which date correspond the DB time "dbti"?
264     //
265     if ( convert ){
266     printf("\n DB time %u is %s %s \n",dbti,dbtime->ConvertTime(tzone,dbti).Data(),tzone.Data());
267     };
268     //
269 mocchiut 1.3 // convert OBT to date
270 mocchiut 1.1 //
271     if ( convobt && convobtts ){
272     UInt_t id = 0;
273     myquery.str("");
274     myquery << "select ";
275     myquery << " ID";
276     myquery << " from GL_ROOT where NAME=\"" << tsfile.Data() << "\";";
277     pResult = dbc->Query(myquery.str().c_str());
278     if ( pResult ){
279     Row = pResult->Next();
280     if ( Row ){
281     id = (UInt_t)atoll(Row->GetField(0));
282     delete pResult;
283     GL_TIMESYNC *ctime = new GL_TIMESYNC(id,"ID",dbc);
284     UInt_t abtime = ctime->DBabsTime(obt);
285     TString thetime = dbtime->ConvertTime(tzone,abtime);
286     printf("\n OBT %u in the file %s corresponds to DBtime %u and date %s %s \n",obt,tsfile.Data(),abtime,thetime.Data(),tzone.Data());
287     delete ctime;
288     };
289     };
290     };
291 mocchiut 1.3 if ( (convobt && !convobtts) ){
292 mocchiut 1.1 printf("\n To convert a OBT to a date you must provide both OBT and file to be used for time sync \n");
293     };
294     //
295 mocchiut 1.3 // convert OBT to Resurs seconds
296     //
297     if ( convres && convobtts ){
298     UInt_t id = 0;
299     myquery.str("");
300     myquery << "select ";
301     myquery << " ID";
302     myquery << " from GL_ROOT where NAME=\"" << tsfile.Data() << "\";";
303     pResult = dbc->Query(myquery.str().c_str());
304     if ( pResult ){
305     Row = pResult->Next();
306     if ( Row ){
307     id = (UInt_t)atoll(Row->GetField(0));
308     delete pResult;
309     GL_TIMESYNC *ctime = new GL_TIMESYNC(id,"ID",dbc);
310     UInt_t restime = ctime->ResursTime(res);
311     //UInt_t abtime = ctime->DBabsTime(obt);
312     //
313     // TString thetime = dbtime->ConvertTime(tzone,abtime);
314     printf("\n OBT %u in the file %s corresponds to Resurs time %u \n",res,tsfile.Data(),restime);
315     delete ctime;
316     };
317     };
318     };
319     if ( (convres && !convobtts) ){
320     printf("\n To convert a OBT to the Resurs time you must provide both OBT and file to be used for time sync \n");
321     };
322     //
323 mocchiut 1.1 // Which run contains the date "runtime"?
324     //
325     if ( ruti ){
326     //
327 mocchiut 1.2 TDatime ti = TDatime(runtime.Data());
328     //
329     TTimeStamp *time = new TTimeStamp((UInt_t)ti.GetYear(),(UInt_t)ti.GetMonth(),(UInt_t)ti.GetDay(),(UInt_t)ti.GetHour(),(UInt_t)ti.GetMinute(),(UInt_t)ti.GetSecond(),0,true,0);
330     //
331     UInt_t dbti = time->GetSec();
332 mocchiut 1.1 //
333     TString thetime = dbtime->UnConvertTime(tzone,dbti);
334     //
335 mocchiut 1.2 ti = TDatime(thetime.Data());
336     TTimeStamp *time2 = new TTimeStamp((UInt_t)ti.GetYear(),(UInt_t)ti.GetMonth(),(UInt_t)ti.GetDay(),(UInt_t)ti.GetHour(),(UInt_t)ti.GetMinute(),(UInt_t)ti.GetSecond(),0,true,0);
337     //
338     UInt_t mytime = time2->GetSec();
339     //
340 mocchiut 1.1 Bool_t found = false;
341     //
342     myquery.str("");
343     myquery << "select ";
344     myquery << " ID ";
345     myquery << " from GL_RUN where RUNHEADER_TIME<=" << mytime << " AND "
346     << " RUNTRAILER_TIME>=" << mytime << " ;";
347     // printf("myquery is %s \n",myquery.str().c_str());
348     pResult = dbc->Query(myquery.str().c_str());
349     for( r=0; r < 1000; r++){
350     Row = pResult->Next();
351     if( Row == NULL ) break;
352     found = true;
353     printf("\n Date %s %s (DB time %u ) is contained in run %u \n",runtime.Data(),tzone.Data(),mytime,(UInt_t)atoll(Row->GetField(0)));
354     };
355     myquery.str("");
356     myquery << "select ";
357     myquery << " ID ";
358     myquery << " from GL_RUN_TRASH where BELONGED_TO='GL_RUN' AND RUNHEADER_TIME<=" << mytime << " AND "
359     << " RUNTRAILER_TIME>=" << mytime << " ;";
360     // printf("myquery is %s \n",myquery.str().c_str());
361     pResult = dbc->Query(myquery.str().c_str());
362     for( r=0; r < 1000; r++){
363     Row = pResult->Next();
364     if( Row == NULL ) break;
365     printf("\n Date %s %s (DB time %u ) is contained in run %u in the GL_RUN_TRASH table \n",runtime.Data(),tzone.Data(),mytime,(UInt_t)atoll(Row->GetField(0)));
366     found = true;
367     };
368     //
369     if ( !found ){
370     printf("\n No run contains date %s %s (DB time %u )\n",runtime.Data(),tzone.Data(),mytime);
371     };
372     //
373     };
374     //
375     // Which tle must be used for the date "tletime"?
376     //
377     if ( dtle ){
378     //
379 mocchiut 1.2 //
380     TDatime ti = TDatime(runtime.Data());
381     //
382     TTimeStamp *time = new TTimeStamp((UInt_t)ti.GetYear(),(UInt_t)ti.GetMonth(),(UInt_t)ti.GetDay(),(UInt_t)ti.GetHour(),(UInt_t)ti.GetMinute(),(UInt_t)ti.GetSecond(),0,true,0);
383     //
384     UInt_t dbti = time->GetSec();
385 mocchiut 1.1 //
386     TString thetime = dbtime->UnConvertTime(tzone,dbti);
387     //
388 mocchiut 1.2 ti = TDatime(thetime.Data());
389     TTimeStamp *time2 = new TTimeStamp((UInt_t)ti.GetYear(),(UInt_t)ti.GetMonth(),(UInt_t)ti.GetDay(),(UInt_t)ti.GetHour(),(UInt_t)ti.GetMinute(),(UInt_t)ti.GetSecond(),0,true,0);
390     //
391     UInt_t mytime = time2->GetSec();
392 mocchiut 1.1 //
393     myquery.str("");
394 mocchiut 1.2 myquery << " select ID,TLE1,TLE2,TLE3 from GL_TLE where FROM_TIME<='" << time2->AsString("s") << "' ORDER BY FROM_TIME DESC LIMIT 1;";
395 mocchiut 1.1 // myquery << " from GL_TLE where FROM_TIME>=" << mytime << " ORDER BY FROM_TIME ASC LIMIT 1;";
396     // printf("myquery is %s \n",myquery.str().c_str());
397     pResult = dbc->Query(myquery.str().c_str());
398     Row = pResult->Next();
399     if ( !Row ){
400     printf("\n No TLE in the DB for date %s %s (DB time %u )\n",tletime.Data(),tzone.Data(),mytime);
401     };
402     printf("\n Date %s %s (DB time %u ) is contained in TLE %u \n",tletime.Data(),tzone.Data(),mytime,(UInt_t)atoll(Row->GetField(0)));
403     printf("\n%s\n",Row->GetField(1));
404     printf("%s\n",Row->GetField(2));
405     printf("%s\n",Row->GetField(3));
406     //
407     FILE *tlefile;
408     tlefile = fopen("tle.txt","w");
409     fprintf(tlefile,"%s\n",Row->GetField(1));
410     fprintf(tlefile,"%s\n",Row->GetField(2));
411     fprintf(tlefile,"%s\n",Row->GetField(3));
412     fclose (tlefile);
413     //
414     printf("\n TLE has been dumped in file tle.txt \n");
415     };
416     //
417     // Which run contains the dbtime "runtime2"?
418     //
419     if ( ruti2 ){
420     //
421     UInt_t mytime = runtime2;
422     //
423     Bool_t found = false;
424     myquery.str("");
425     myquery << "select ";
426     myquery << " ID ";
427     myquery << " from GL_RUN where RUNHEADER_TIME<=" << mytime << " AND "
428     << " RUNTRAILER_TIME>=" << mytime << " ;";
429     // printf("myquery is %s \n",myquery.str().c_str());
430     pResult = dbc->Query(myquery.str().c_str());
431     for( r=0; r < 1000; r++){
432     Row = pResult->Next();
433     if( Row == NULL ) break;
434     printf("\n DB time %u is contained in run %u \n",mytime,(UInt_t)atoll(Row->GetField(0)));
435     found = true;
436     };
437     //
438     myquery.str("");
439     myquery << "select ";
440     myquery << " ID ";
441     myquery << " from GL_RUN_TRASH where BELONGED_TO='GL_RUN' AND RUNHEADER_TIME<=" << mytime << " AND "
442     << " RUNTRAILER_TIME>=" << mytime << " ;";
443     // printf("myquery is %s \n",myquery.str().c_str());
444     pResult = dbc->Query(myquery.str().c_str());
445     for( r=0; r < 1000; r++){
446     Row = pResult->Next();
447     if( Row == NULL ) break;
448     printf("\n DB time %u is contained in run %u in the GL_RUN_TRASH table \n",mytime,(UInt_t)atoll(Row->GetField(0)));
449     found = true;
450     };
451     //
452     if ( !found ){
453     printf("\n No run contains DB time %u \n",mytime);
454     };
455     //
456     };
457     //
458     // To which file the run "run" belongs?
459     //
460     if ( run != 0 ){
461     Bool_t found = false;
462     glrun->Clear();
463     error = glrun->Query_GL_RUN(run,dbc);
464     glroot->Clear();
465     error = glroot->Query_GL_ROOT(glrun->ID_ROOT_L0,dbc);
466     if ( glrun->ID_ROOT_L0 ){
467     if ( error ){
468     printf(" Error querying the DB! \n");
469     exit(-4);
470     };
471     printf("\n Run %u belongs to file %s \n",run,(glroot->PATH+glroot->NAME).Data());
472     found = true;
473     };
474     //
475     myquery.str("");
476     myquery << "select ";
477     myquery << " ID,FILENAMEL0,FILENAMEL2 ";
478     myquery << " from GL_RUN_TRASH where BELONGED_TO='GL_RUN' AND ID=" << run << "; ";
479     pResult = dbc->Query(myquery.str().c_str());
480     for( r=0; r < 1000; r++){
481     Row = pResult->Next();
482     if( Row == NULL ) break;
483     printf("\n RUN %u has been deleted and now is contained in the GL_RUN_TRASH table \n",run);
484     printf("\n RUN %u belonged to L0 file %s and L2 file %s \n",run,Row->GetField(1),Row->GetField(2));
485     found = true;
486     };
487     //
488     if ( !found ) printf("\n No run with ID=%u in the DB!\n",run);
489     };
490     //
491     // Which runs are contained in the file "filename"?
492     //
493     if ( strcmp(filename.Data(),"") ){
494     // ----------------
495     Bool_t found = false;
496     Int_t ID = 0;
497     Int_t ID_RAW = 0;
498     //
499     const char *rawpath = "";
500     const char *rawname = "";
501     //
502     myquery.str("");
503     myquery << "select ";
504     myquery << " ID";
505     myquery << ",ID_RAW";
506     myquery << ",PATH";
507     myquery << ",NAME";
508     myquery << " from GL_ROOT where NAME=\"" << filename.Data() << "\";";
509     pResult = dbc->Query(myquery.str().c_str());
510     for( r=0; r < 1000; r++){
511     Row = pResult->Next();
512     if( Row == NULL ) break;
513     for( t = 0; t < pResult->GetFieldCount(); t++){
514     if(t==0) ID = atoi(Row->GetField(t));
515     if(t==1) ID_RAW = atoi(Row->GetField(t));
516     };
517     };
518     delete pResult;
519     if ( !ID && !ID_RAW ){
520     printf("\n No file with name %s in the DB!\n",filename.Data());
521     } else {
522     myquery.str("");
523     myquery << "select ";
524     myquery << " ID,RUNHEADER_TIME,RUNTRAILER_TIME ";
525     myquery << " from GL_RUN where ID_ROOT_L0=" << ID << ";";
526     pResult = dbc->Query(myquery.str().c_str());
527     for( r=0; r < 1000; r++){
528     Row = pResult->Next();
529     if( Row == NULL ) break;
530     found = true;
531     if ( !r ) printf("\n File %s contains the following runs: \n\n",filename.Data());
532     TString UTC="UTC";
533 mocchiut 1.2 printf(" => ID = %i --> the run started at %s UTC ended at %s UTC \n\n",(UInt_t)atoll(Row->GetField(0)),dbtime->ConvertTime(UTC,(UInt_t)atoll(Row->GetField(1))).Data(),dbtime->ConvertTime(UTC,(UInt_t)atoll(Row->GetField(2))).Data());
534 mocchiut 1.1 };
535     delete pResult;
536     myquery.str("");
537     myquery << "select ";
538     myquery << " ID,RUNHEADER_TIME,RUNTRAILER_TIME ";
539     myquery << " from GL_RUN_TRASH where BELONGED_TO='GL_RUN' AND FILENAMEL0='" << filename.Data() << "' ;";
540     pResult = dbc->Query(myquery.str().c_str());
541     for( r=0; r < 1000; r++){
542     Row = pResult->Next();
543     if( Row == NULL ) break;
544     if ( !r ) printf("\n File %s contains the following DELETED runs: \n\n",filename.Data());
545     TString UTC="UTC";
546 mocchiut 1.2 printf(" => ID = %i --> the run started at %s UTC ended at %s UTC \n\n",(UInt_t)atoll(Row->GetField(0)),dbtime->ConvertTime(UTC,(UInt_t)atoll(Row->GetField(1))).Data(),dbtime->ConvertTime(UTC,(UInt_t)atoll(Row->GetField(2))).Data());
547 mocchiut 1.1 };
548     //
549     if ( !found ){
550     printf("\n No run associated to the file %s \n",filename.Data());
551     };
552     myquery.str("");
553     myquery << "select ";
554     myquery << " PATH,NAME";
555     myquery << " from GL_RAW where ID=" << ID_RAW << ";";
556     pResult = dbc->Query(myquery.str().c_str());
557     for( r=0; r < 1000; r++){
558     Row = pResult->Next();
559     if( Row == NULL ) break;
560     for( t = 0; t < pResult->GetFieldCount(); t++){
561     if(t==0) rawpath = Row->GetField(t);
562     if(t==1) rawname = Row->GetField(t);
563     };
564     };
565     delete pResult;
566     printf("\n File %s belongs to raw data file %s/%s \n",filename.Data(),rawpath,rawname);
567     };
568     };
569     //
570     // Close the DB connection
571     //
572     if ( dbc ) dbc->Close();
573     //
574     printf("\n");
575     //
576     exit(0);
577     }

  ViewVC Help
Powered by ViewVC 1.1.23