Changeset 10474


Ignore:
Timestamp:
04/27/11 14:45:41 (14 years ago)
Author:
lyard
Message:
Added more services + define for single run-fits or not
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/FACT++/src/dataLogger.cc

    r10453 r10474  
    6262#include <sys/stat.h>
    6363
    64 //#define HAS_FITS
     64#define HAS_FITS
     65//#define ONE_RUN_FITS_ONLY
    6566
    6667#include <fstream>
     
    7071
    7172#ifdef HAS_FITS
    72 //#include <astroroot.h>
    7373#include "Fits.h"
    7474#endif
     75
     76//Dim structures
     77struct DataLoggerStats {
     78        long long sizeWritten;
     79        long long freeSpace;
     80        long writingRate;
     81};
     82
     83struct NumSubAndFitsType {
     84        int numSubscriptions;
     85        int numOpenFits;
     86};
    7587
    7688class DataLogger : public StateMachineDim, DimInfoHandler
     
    107119        ///run number (-1 means no run number specified)
    108120        int fRunNumber;
    109         ///Current year
    110 //      short fYear;
    111         ///Current Month
    112 //      short fMonth;
    113         ///Current Day
    114 //      short fDay;
    115         ///Current Hour
    116 //      short fHour;
    117         ///Current Minute
    118 //      short fMin;
    119         ///Current Second
    120 //      short fSec;
    121         ///Current Milliseconds
    122 //      int fMs;
    123121        ///Current Service Quality
    124122        int fQuality;
     
    216214                        if (*numCopies < 1)
    217215                        {
     216                                if (dimInfo)
     217                                delete dimInfo;
    218218#ifdef HAS_FITS
    219219                                if (dailyFile.IsOpen())
     
    222222                                        runFile.Close();
    223223#endif
    224                                 if (dimInfo)
    225                                 delete dimInfo;
    226224                                if (numCopies) 
    227225                                delete numCopies;
     
    268266        ///Allocate the buffers required for fits
    269267        void AllocateFITSBuffers(SubscriptionType& sub);
     268               
     269#ifdef ONE_RUN_FITS_ONLY
    270270        ///FITS file for runs. only one, hence dealt with in the dataLogger itself
    271271        FITS* fRunFitsFile;
    272 #endif
     272#endif //one_run_fits_only
     273#endif//has_fits
    273274public:
    274275        ///checks with fServiceList whether or not the services got updated
    275         void CheckForServicesUpdate();
     276        bool CheckForServicesUpdate();
    276277
    277278private:       
     
    292293        long long fBaseSizeRun;
    293294        ///Service for opened files
    294         DimService* fOpenedFiles;
    295         char* fDimBuffer;
    296         inline void NotifyOpenedFile(std::string name, int type);
     295        DimService* fOpenedDailyFiles;
     296        DimService* fOpenedRunFiles;
     297        DimService* fNumSubAndFits;
     298        NumSubAndFitsType fNumSubAndFitsData;
     299//      char* fDimBuffer;
     300        inline void NotifyOpenedFile(std::string name, int type, DimService* service);
    297301       
    298302}; //DataLogger
     
    312316const char* DataLogger::fRunNumberInfo = "RUN_NUMBER";
    313317
     318
    314319void DataLogger::ServicesMonitoring()
    315320{
    316321                //create the DIM service
    317322                int dataSize = 2*sizeof(long long) + sizeof(long);
    318                 char* data = new char[dataSize];
    319                 memset(data, 0, dataSize);
    320                 DimDescribedService srvc((GetName()+"/STATS").c_str(), "x:2;l:1", static_cast<void*>(data), dataSize,
    321                                         "Add description here");
     323
     324                DataLoggerStats statVar;
     325                statVar.sizeWritten = 0;
     326                statVar.freeSpace = 0;
     327                statVar.writingRate = 0;
     328
     329                struct statvfs vfs;
     330                if (!statvfs(fDailyFileName.c_str(), &vfs))
     331                        statVar.freeSpace = vfs.f_bsize*vfs.f_bavail;
     332                else
     333                        statVar.freeSpace = -1;
     334//        DimDescribedService srvc((GetName()+"/STATS").c_str(), "x:2;l:1", &statVar, dataSize,//static_cast<void*>(data), dataSize,
     335//                                        "Add description here");
     336                DimService srvc ("DATA_LOGGER/STATS", "x:2;l:1", &statVar, dataSize);
    322337                double deltaT = 1;
    323338                fPreviousSize = 0;
    324 
    325                 long long& targetSize  = reinterpret_cast<long long*>(data)[0];
    326                 long long& targetFreeSpace  = reinterpret_cast<long long*>(data)[1];
    327                 long& targetRate = reinterpret_cast<long*>(data + 2*sizeof(long long))[0];
    328339                //loop-wait for broadcast
    329340                while (fContinueMonitoring)
     
    371382                                fFileSizesMap[fFullRunReportFileName] = st.st_size;
    372383                        }       
    373                         if (fDailyLogFile.is_open())
    374                         {
    375                                 struct statvfs vfs;
    376                                 statvfs(fDailyFileName.c_str(), &vfs);
    377                                 targetFreeSpace = vfs.f_bsize*vfs.f_bavail;
    378                         }
     384
     385                        if (!statvfs(fDailyFileName.c_str(), &vfs))
     386                                statVar.freeSpace = vfs.f_bsize*vfs.f_bavail;
     387                        else
     388                                statVar.freeSpace = -1;
     389                       
    379390                        //sum up all the file sizes. past and present
    380                         targetSize = 0;
     391                        statVar.sizeWritten = 0;
    381392                        for (std::map<std::string, long long>::iterator it=fFileSizesMap.begin(); it != fFileSizesMap.end();  it++)
    382                                 targetSize += it->second;
    383                         targetSize -= fBaseSizeDaily;
    384                         targetSize -= fBaseSizeRun;
     393                                statVar.sizeWritten += it->second;
     394                        statVar.sizeWritten -= fBaseSizeDaily;
     395                        statVar.sizeWritten -= fBaseSizeRun;
    385396                        //FIXME get the actual time elapsed
    386                         targetRate = (targetSize - fPreviousSize)/deltaT; 
    387                         fPreviousSize = targetSize;
    388 //                      if (targetRate != 0) //if data has been written
    389                         {
    390 std::cout << "fBaseSizeDaily: " << fBaseSizeDaily << " fBaseSizeRun: " << fBaseSizeRun << std::endl;
    391 //std::cout << "Written Size: " << targetSize << ", free space: " << targetFreeSpace << ", data rate: " << targetRate << " Bytes/s" << std::endl;
    392 
    393                                 srvc.updateService(static_cast<void*>(data), dataSize);
     397                        statVar.writingRate = (statVar.sizeWritten - fPreviousSize)/deltaT; 
     398                        fPreviousSize = statVar.sizeWritten;
     399                        if (statVar.writingRate != 0) //if data has been written
     400                        {
     401//std::cout << "rate: " << statVar.writingRate << std::endl;
     402                                srvc.updateService(&statVar, dataSize);//static_cast<void*>(data), dataSize);
    394403                        }
    395404                }
    396                 delete[] data;
    397405}
    398406
     
    408416{       
    409417                //initialize member data
    410                 fDailyFileName = ".";
    411                 fRunFileName = ".";
     418                fDailyFileName = "/home/lyard/log";//".";
     419                fRunFileName = "/home/lyard/log";//".";
    412420                fRunNumber = 12345;
    413421#ifdef HAS_FITS
     422#ifdef ONE_RUN_FITS_ONLY
    414423                fRunFitsFile = NULL;
     424#endif
    415425#endif
    416426                //Give a name to this machine's specific states
     
    422432
    423433        /*Add the possible transitions for this machine*/
    424 
    425434                AddTransition(kSM_DailyOpen, fTransStart, kSM_Ready, kSM_BadDailyConfig)
    426                     (boost::bind(&DataLogger::StartPlease, this))
    427                     ("start the daily logging. daily file location must be specified already");
     435                    (boost::bind(&DataLogger::StartPlease, this));
     436//                    ("start the daily logging. daily file location must be specified already");
    428437
    429438                AddTransition(kSM_Ready, fTransStop, kSM_DailyOpen, kSM_WaitingRun, kSM_Logging)
    430                     (boost::bind(&DataLogger::GoToReadyPlease, this))
    431                     ("stop the data logging");
     439                    (boost::bind(&DataLogger::GoToReadyPlease, this));
     440//                   ("stop the data logging");
    432441
    433442                AddTransition(kSM_Logging, fTransStartRun, kSM_WaitingRun, kSM_BadRunConfig)
    434                     (boost::bind(&DataLogger::StartRunPlease, this))
    435                     ("start the run logging. run file location must be specified already.");
     443                    (boost::bind(&DataLogger::StartRunPlease, this));
     444//                    ("start the run logging. run file location must be specified already.");
    436445
    437446                AddTransition(kSM_WaitingRun, fTransStopRun, kSM_Logging)
    438                     (boost::bind(&DataLogger::StopRunPlease, this))
    439                     ("");
     447                    (boost::bind(&DataLogger::StopRunPlease, this));
     448//                    ("");
    440449
    441450                AddTransition(kSM_Ready, fTransReset, kSM_Error, kSM_BadDailyConfig, kSM_BadRunConfig, kSM_Error)
    442                     (boost::bind(&DataLogger::GoToReadyPlease, this))
    443                     ("transition to exit error states. dunno if required or not, would close the daily file if already openned.");
     451                    (boost::bind(&DataLogger::GoToReadyPlease, this));
     452//                    ("transition to exit error states. dunno if required or not, would close the daily file if already openned.");
    444453
    445454                AddTransition(kSM_WaitingRun, fTransWait, kSM_DailyOpen)
     
    449458       
    450459                AddConfiguration(fConfigDay, "C", kSM_Ready, kSM_BadDailyConfig)
    451                     (boost::bind(&DataLogger::ConfigureDailyFileName, this, _1))
    452                     ("configure the daily file location. cannot be done before the file is actually opened");
     460                    (boost::bind(&DataLogger::ConfigureDailyFileName, this, _1));;
     461//                    ("configure the daily file location. cannot be done before the file is actually opened");
    453462
    454463                AddConfiguration(fConfigRun, "C", kSM_Ready, kSM_BadDailyConfig, kSM_DailyOpen, kSM_WaitingRun, kSM_BadRunConfig)
    455                     (boost::bind(&DataLogger::ConfigureRunFileName, this, _1))
    456                     ("configure the run file location. cannot be done before the file is actually opened, and not in a dailly related error.");
     464                    (boost::bind(&DataLogger::ConfigureRunFileName, this, _1));
     465//                    ("configure the run file location. cannot be done before the file is actually opened, and not in a dailly related error.");
    457466
    458467                //Provide a logging command
     
    464473                    (boost::bind(&DataLogger::LogMessagePlease, this, _1));
    465474
    466                 fServiceList.SetHandler(this);
     475                fServiceList.SetHandler(this);
    467476                CheckForServicesUpdate();
    468477               
     
    473482                fBaseSizeRun = 0;
    474483                //start the open files service
    475                 fDimBuffer = new char[256];
    476                 memset(fDimBuffer, 0, sizeof(int));
    477                 fDimBuffer[sizeof(int)] = '\0';
     484//              fDimBuffer = new char[256];
     485//              memset(fDimBuffer, 0, sizeof(int));
     486//              fDimBuffer[sizeof(int)] = '\0';
     487
    478488                //gives the entire buffer size. Otherwise, dim overwrites memory at bizarre locations if smaller size is given at creation time.
    479                 fOpenedFiles =  new DimDescribedService((GetName()+"/FILENAME").c_str(), "i:1;C", static_cast<void*>(fDimBuffer), 256,
    480                                                         "Add description here");
    481                
    482                
     489//        fOpenedFiles =        new DimDescribedService((GetName()+"/FILENAME").c_str(), "i:1;C", static_cast<void*>(fDimBuffer), 256, "Add description here");
     490                fOpenedDailyFiles = new DimService((GetName() + "/FILENAME_DAILY").c_str(), const_cast<char*>(""));//"i:1;C", static_cast<void*>(fDimBuffer), 256);
     491                fOpenedRunFiles = new DimService((GetName() + "/FILENAME_RUN").c_str(), const_cast<char*>(""));
     492                fOpenedDailyFiles->setQuality(0);
     493                fOpenedRunFiles->setQuality(0);
     494                fOpenedDailyFiles->updateService();
     495                fOpenedRunFiles->updateService();
     496                fNumSubAndFitsData.numSubscriptions = 0;
     497                fNumSubAndFitsData.numOpenFits = 0;
     498                fNumSubAndFits = new DimService((GetName() + "/NUM_SUBS").c_str(), "i:2", &fNumSubAndFitsData, sizeof(NumSubAndFitsType));
     499
    483500}
    484501// --------------------------------------------------------------------------
     
    490507//
    491508//FIXME The service must be udpated so that I get the first notification. This should not be
    492 void DataLogger::CheckForServicesUpdate()
     509bool DataLogger::CheckForServicesUpdate()
    493510{
    494 
     511        bool serviceUpdated = false;
    495512        //get the current server list
    496513        const std::vector<std::string> serverList = fServiceList.GetServerList();
     
    505522                                break;
    506523                if (givenServers == serverList.end())//server vanished. Remove it
     524                {       
    507525                        toBeDeleted.push_back(cListe->first);
     526                        serviceUpdated = true;
     527                }
     528                       
    508529        }
    509530        for (std::vector<std::string>::const_iterator it = toBeDeleted.begin(); it != toBeDeleted.end(); it++)
    510531                fServiceSubscriptions.erase(*it);
    511 
    512532        //now crawl through the list of servers, and see if there was some updates
    513533        for (std::vector<std::string>::const_iterator i=serverList.begin(); i!=serverList.end();i++)
     
    535555                                {
    536556                                        toBeDeleted.push_back(serverSubs->first);
     557                                        serviceUpdated = true;
    537558                                }       
    538559                        }
     
    547568                                {//service not found. Add it
    548569                                        cSubs->second[*givenSubs].dimInfo = new DimStampedInfo(((*i) + "/" + *givenSubs).c_str(), const_cast<char*>(""), this);
     570                                        serviceUpdated = true;
    549571                                }       
    550572                        }
     
    559581                                        continue;
    560582                                liste[*j].dimInfo = new DimStampedInfo(((*i) + "/" + (*j)).c_str(), const_cast<char*>(""), this);
     583                                serviceUpdated = true;
    561584                        }
    562585                }       
    563586        }
     587        return serviceUpdated;
    564588}
    565589// --------------------------------------------------------------------------
     
    569593DataLogger::~DataLogger()
    570594{
     595        //release the services subscriptions
     596        fServiceSubscriptions.clear();
    571597        //exit the monitoring loop
    572598        fContinueMonitoring = false;
    573         delete[] fDimBuffer;
    574         delete fOpenedFiles;
     599//      delete[] fDimBuffer;
    575600        fMonitoringThread.join();
    576601        //close the files
     
    583608        if (fRunReportFile.is_open())
    584609                fRunReportFile.close();
    585         //release the services subscriptions
    586         fServiceSubscriptions.clear();
     610        delete fOpenedDailyFiles;
     611        delete fOpenedRunFiles;
     612        delete fNumSubAndFits;
     613//TODO notify that all files were closed
    587614#ifdef HAS_FITS
     615#ifdef ONE_RUN_FITS_ONLY
    588616        if (fRunFitsFile != NULL)
    589617                delete fRunFitsFile;
    590618        fRunFitsFile = NULL;
     619#endif
    591620#endif
    592621}
     
    719748{
    720749        DimInfo* I = getInfo();
     750        SubscriptionsListType::iterator x;
     751        std::map<std::string, SubscriptionType>::iterator y;
    721752        if (I==NULL)
    722753        {
    723                 CheckForServicesUpdate();
     754                if (CheckForServicesUpdate())
     755                {
     756                        //services were updated. Notify
     757                        fNumSubAndFitsData.numSubscriptions = 0;
     758                        for (x=fServiceSubscriptions.begin(); x != fServiceSubscriptions.end(); x++)
     759                                fNumSubAndFitsData.numSubscriptions += x->second.size();
     760                        fNumSubAndFits->updateService();
     761                }
    724762                return;
    725763        }
     
    727765        //this is a fix for a bug that provides bad Infos when a server starts
    728766        bool found = false;
    729         SubscriptionsListType::iterator x;
    730         std::map<std::string, SubscriptionType>::iterator y;
    731767        for (x=fServiceSubscriptions.begin(); x != fServiceSubscriptions.end(); x++)
    732768        {//find current service is subscriptions
     
    933969int DataLogger::ConfigureDailyFileName(const Event& evt)
    934970{
     971std::cout << "Configure Daily File Name" << std::endl;
    935972        if (evt.GetText() != NULL)
    936973                fDailyFileName = std::string(evt.GetText());   
     
    949986int DataLogger::ConfigureRunFileName(const Event& evt)
    950987{
     988std::cout << "Configure Run File Name" << std::endl;
    951989        if (evt.GetText() != NULL)
    952990                fRunFileName = std::string(evt.GetText());
     
    9761014//!             this is not a problem though because file are not opened so often.
    9771015//! @ param type the type of the opened file. 0 = none open, 1 = log, 2 = text, 4 = fits
    978 inline void DataLogger::NotifyOpenedFile(std::string name, int type)
     1016inline void DataLogger::NotifyOpenedFile(std::string name, int type, DimService* service)
    9791017{
    9801018//std::cout << "name: " << name << " size: " << name.size() << std::endl;
    981         reinterpret_cast<int*>(fDimBuffer)[0] = type;
    982         strcpy(&fDimBuffer[sizeof(int)], name.c_str());
    983         fOpenedFiles->updateService(static_cast<void*>(fDimBuffer), name.size() + 1 + sizeof(int));
     1019//      reinterpret_cast<int*>(fDimBuffer)[0] = type;
     1020//      strcpy(&fDimBuffer[sizeof(int)], name.c_str());
     1021        service->setQuality(type);
     1022        service->updateService(const_cast<char*>(name.c_str()));
     1023//      fOpenedFiles->updateService(static_cast<void*>(fDimBuffer), name.size() + 1 + sizeof(int));
    9841024}
    9851025// --------------------------------------------------------------------------
     
    10171057        fPreviousSize = 0;
    10181058        //notify that files were opened
    1019         NotifyOpenedFile(sTime.str(), 3);
     1059        std::string actualTargetDir;
     1060        if (fDailyFileName == ".")
     1061        {
     1062                char currentPath[FILENAME_MAX];
     1063                getcwd(currentPath, sizeof(currentPath));
     1064                actualTargetDir = currentPath;
     1065        }
     1066        else
     1067        {
     1068                actualTargetDir = fDailyFileName;       
     1069        }
     1070std::cout << actualTargetDir << '/' << sTime.str() << std::endl;
     1071        NotifyOpenedFile(actualTargetDir + '/' + sTime.str(), 3, fOpenedDailyFiles);
    10201072       
    10211073       
     
    10561108                        fFileSizesMap[partialName] = 0;
    10571109                }
    1058                 sub.dailyFile.Open(partialName, serviceName, NULL);
     1110                sub.dailyFile.Open(partialName, serviceName, NULL, &fNumSubAndFitsData.numOpenFits);
    10591111                //notify the opening
    1060                 NotifyOpenedFile(sTime.str() + '_' + serviceName, 4);
    1061                
     1112                std::string actualTargetDir;
     1113                if (fDailyFileName == ".")
     1114                {
     1115                        char currentPath[FILENAME_MAX];
     1116                        getcwd(currentPath, sizeof(currentPath));
     1117                        actualTargetDir = currentPath;
     1118                }
     1119                else
     1120                {
     1121                        actualTargetDir = fDailyFileName;       
     1122                }               
     1123                NotifyOpenedFile(actualTargetDir + '/' + sTime.str(), 4, fOpenedDailyFiles);
     1124                fNumSubAndFits->updateService();
    10621125        }
    10631126        if (!sub.runFile.IsOpen() && (GetCurrentState() == kSM_Logging))
     
    10651128                std::stringstream sRun;
    10661129                sRun << fRunNumber;
     1130#ifdef ONE_RUN_FITS_ONLY
    10671131                std::string partialName = fRunFileName + '/' + sRun.str() + ".fits";//'_' + serviceName + ".fits";
    10681132                if (fRunFitsFile == NULL)
    10691133                {
     1134#else
     1135                std::string partialName = fRunFileName + '/' + sRun.str() + '_' + serviceName + ".fits";
     1136#endif
    10701137                        //get the size of the file we're about to open
    10711138                        if (fFileSizesMap.find(partialName) == fFileSizesMap.end())
     
    10781145                                fFileSizesMap[partialName] = 0;
    10791146                        }
     1147#ifdef ONE_RUN_FITS_ONLY
    10801148                        try
    10811149                        {
    10821150                                fRunFitsFile = new FITS(partialName, RWmode::Write);   
     1151                                (fNumSubAndFitsData.numOpenFits)++;
    10831152                        }       
    10841153                        catch (CCfits::FitsError e)
     
    10881157                                throw runtime_error(err.str());
    10891158                        }
    1090                         NotifyOpenedFile(sRun.str(), 4);// + '_' + serviceName, 4);
     1159#endif
     1160                        std::string actualTargetDir;
     1161                        if (fRunFileName == ".")
     1162                        {
     1163                                char currentPath[FILENAME_MAX];
     1164                                getcwd(currentPath, sizeof(currentPath));
     1165                                actualTargetDir = currentPath;
     1166                        }
     1167                        else
     1168                        {
     1169                                actualTargetDir = fRunFileName;
     1170                        }               
     1171                        NotifyOpenedFile(actualTargetDir + '/' + sRun.str(), 4, fOpenedRunFiles);// + '_' + serviceName, 4);
     1172#ifdef ONE_RUN_FITS_ONLY
    10911173                }
    1092                 sub.runFile.Open(partialName, serviceName, fRunFitsFile);
     1174                sub.runFile.Open(partialName, serviceName, fRunFitsFile, &fNumSubAndFitsData.numOpenFits);
     1175#else
     1176                sub.runFile.Open(partialName, serviceName, NULL, &fNumSubAndFitsData.numOpenFits);
     1177#endif //one_run_fits_only
     1178           fNumSubAndFits->updateService();
     1179
    10931180        }
    10941181}       
     
    12181305                fFileSizesMap[fFullRunReportFileName] = 0;
    12191306        }
    1220         NotifyOpenedFile(sRun.str(), 3);
     1307        std::string actualTargetDir;
     1308        if (fRunFileName == ".")
     1309        {
     1310                char currentPath[FILENAME_MAX];
     1311                getcwd(currentPath, sizeof(currentPath));
     1312                actualTargetDir = currentPath;
     1313        }
     1314        else
     1315        {
     1316                actualTargetDir = fRunFileName;
     1317        }               
     1318        NotifyOpenedFile(actualTargetDir + '/' + sRun.str(), 3, fOpenedRunFiles);
    12211319       
    12221320        return kSM_Logging;
     
    12421340                                        j->second.runFile.Close();     
    12431341                }
     1342#ifdef ONE_RUN_FITS_ONLY
    12441343        if (fRunFitsFile != NULL)
    12451344        {
    12461345                delete fRunFitsFile;
    12471346                fRunFitsFile = NULL;   
    1248         }
    1249 #endif
     1347std::cout << "FNumSub2: " << fNumSubAndFitsData.numOpenFits << std::endl;
     1348                (fNumSubAndFitsData.numOpenFits)--;
     1349std::cout << "FNumSub3: " << fNumSubAndFitsData.numOpenFits << std::endl;
     1350        }
     1351#endif
     1352#endif
     1353        NotifyOpenedFile("None", 0, fOpenedRunFiles);
     1354        fNumSubAndFits->updateService();
    12501355        return kSM_WaitingRun;
    12511356
     
    12781383                                        j->second.runFile.Close();     
    12791384                }
     1385#ifdef ONE_RUN_FITS_ONLY
    12801386        if (fRunFitsFile != NULL)
    12811387        {
    12821388                delete fRunFitsFile;
    1283                 fRunFitsFile = NULL;   
    1284         }
    1285 #endif
     1389                fRunFitsFile = NULL;
     1390                (fNumSubAndFitsData.numOpenFits)--;
     1391        }
     1392#endif
     1393#endif
     1394        if (GetCurrentState() == kSM_Logging)
     1395                NotifyOpenedFile("None", 0, fOpenedRunFiles);
     1396        if (GetCurrentState() == kSM_Logging ||
     1397            GetCurrentState() == kSM_WaitingRun ||
     1398            GetCurrentState() == kSM_DailyOpen)
     1399        {
     1400                NotifyOpenedFile("None", 0, fOpenedDailyFiles);
     1401                fNumSubAndFits->updateService();
     1402        }
    12861403        return kSM_Ready;
    12871404}
     
    13331450
    13341451    logger.SetReady();
    1335  //  logger.StartPlease();
     1452
    13361453    shell.Run();                 // Run the shell
    13371454     logger.SetNotReady();
Note: See TracChangeset for help on using the changeset viewer.