Changeset 10741 for trunk/FACT++/src


Ignore:
Timestamp:
05/18/11 16:00:41 (13 years ago)
Author:
lyard
Message:
added configurable grouping and did some cosmetics to the code (removed tabs)
Location:
trunk/FACT++/src
Files:
3 edited

Legend:

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

    r10725 r10741  
    3535//! @param numDataBytes the number of bytes taken by the variable
    3636//
    37 void Fits::AddStandardColumn(Description& desc, std::string dataFormat, void* dataPointer, long unsigned int numDataBytes)
     37void Fits::AddStandardColumn(Description& desc, string dataFormat, void* dataPointer, long unsigned int numDataBytes)
    3838{
    3939        //check if entry already exist
    40         for (std::vector<Description>::iterator it=fStandardColDesc.begin(); it != fStandardColDesc.end(); it++)
     40        for (vector<Description>::iterator it=fStandardColDesc.begin(); it != fStandardColDesc.end(); it++)
    4141                if (it->name == desc.name)
    4242                        return;
     
    5454//! @param numDataBytes the number of bytes taken by the DIM data.
    5555//     
    56 void Fits::InitDataColumns(std::vector<Description> desc, std::vector<std::string>& dataFormat, void* dataPointer, int numDataBytes)
     56void Fits::InitDataColumns(vector<Description> desc, vector<string>& dataFormat, void* dataPointer, int numDataBytes)
    5757{//we will copy this information here. It duplicates the data, which is not great, but it is the easiest way of doing it right now
    5858        if (desc.size() == dataFormat.size())
     
    6565                for (unsigned int i=0;i<dataFormat.size();i++)
    6666                {
    67                         std::stringstream stt;
     67                        stringstream stt;
    6868                        stt << "Data" << i;
    6969                        fDataColDesc.push_back(Description(stt.str(), "comment", "unit"));
     
    8383//! @param out a pointer to the MessageImp that should be used to log errors
    8484//
    85 void Fits::Open(const std::string& fileName, const std::string& tableName, FITS* file, int* fitsCounter, MessageImp* out)//std::ostream& out)
     85void Fits::Open(const string& fileName, const string& tableName, FITS* file, int* fitsCounter, MessageImp* out)//ostream& out)
    8686{               
    8787//      if (fMess)
     
    9898                catch (CCfits::FitsError e)
    9999                {                       
    100                         std::stringstream str;
     100                        stringstream str;
    101101                        str << "Could not open FITS file " << fileName << " reason: " << e.message();
    102102                        fMess->Error(str);
     
    115115        //concatenate the standard and data columns
    116116        //do it the inneficient way first: its easier and faster to code.
    117         std::vector<std::string> allNames;
    118         std::vector<std::string> allDataTypes;
    119         std::vector<std::string> allUnits;
     117        vector<string> allNames;
     118        vector<string> allDataTypes;
     119        vector<string> allUnits;
    120120        fTotalNumBytes = 0;
    121121        for (unsigned int i=0;i<fStandardColDesc.size();i++)
     
    133133                else
    134134                {
    135                         std::stringstream stt;
     135                        stringstream stt;
    136136                        stt << "Data" << i;
    137137                        allNames.push_back(stt.str());
     
    145145        try
    146146        {
    147                 std::string factTableName = "FACT-" + tableName;
     147                string factTableName = "FACT-" + tableName;
    148148                fTable = fFile->addTable(factTableName, 0, allNames, allDataTypes, allUnits);
    149149                fTable->makeThisCurrent();
     
    159159                        }       
    160160                        //read the table binary data.
    161                         std::vector<string> colName;
     161                        vector<string> colName;
    162162                        bTable->readData(true, colName);
    163163
    164164                        //double check that the data was indeed read from the disk. Go through the fTable instead as colName is empty (yes, it is !)
    165                         std::map<std::string, Column*> cMap = fTable->column();
    166                         std::map<std::string, Column*>::iterator cMapIt;
     165                        map<string, Column*> cMap = fTable->column();
     166                        map<string, Column*>::iterator cMapIt;
    167167
    168168                        for (cMapIt = cMap.begin(); cMapIt != cMap.end(); cMapIt++)
     
    179179        catch(CCfits::FitsError e)
    180180        {
    181                 std::stringstream str;
     181                stringstream str;
    182182                str << "Could not open or create FITS table " << tableName << " in  file " << fileName << " reason: " << e.message();
    183183                fMess->Error(str);
     
    190190                WriteHeaderKeys();
    191191}
     192// --------------------------------------------------------------------------
     193//
     194//!This writes a single header key in the currently open file.
     195//!@param name the key
     196//!@param value the key value
     197//!@param a comment explaining the meaning of the key
    192198template <typename T>
    193199void Fits::WriteSingleHeaderKey(string name, T value, string comment)
     
    199205        catch (CCfits::FitsError e)
    200206        {
    201                 std::stringstream str;
     207                stringstream str;
    202208                str << "Could not add header keys in file " << fFileName << " reason: " << e.message();
    203209                fMess->Error(str);
     
    212218        if (!fTable)
    213219                return;
    214         std::string name;
    215         std::string comment;
    216        
    217 //      float floatValue;
    218 //      double doubleValue;
    219         std::string stringValue;
     220        string name;
     221        string comment;
     222
     223        string stringValue;
    220224
    221225        WriteSingleHeaderKey("EXTREL", 1.0f, "Release Number");
     
    230234        WriteSingleHeaderKey("TIMEREF", "UTC", "Time reference frame");
    231235        WriteSingleHeaderKey("MJDREF", fRefMjD, "Modified Julian Date of origin");
     236    WriteSingleHeaderKey("TSTOP", fEndMjD, "Time of the last receied data");
    232237}
    233238// --------------------------------------------------------------------------
     
    239244{
    240245
    241 //      try
    242 //      {
    243246        fTable->makeThisCurrent();
    244247        int status(0);
    245248        if (fits_insert_rows(fTable->fitsPointer(), fNumRows, 1, &status))
    246249        {
    247                 std::stringstream str;
     250                stringstream str;
    248251                str << "Could not insert row in file " << fFileName << ". cfitsio error code: " << status;
    249252                fMess->Error(str);
    250253        }
    251 //              fTable->insertRows(fNumRows);
    252 //      }
    253 //      catch(CCfits::FitsError e)
    254 //      {
    255 //              std::stringstream str;
    256 //              str << "Could not insert row in file " << fFileName << " reason: " << e.message();
    257 //              fMess->Error(str);
    258 //      }
    259254        fNumRows++;
    260255
     
    273268        {
    274269                const char * charSrc = static_cast<char*>(fStandardPointers[i]);
    275 
    276270                reverse_copy(charSrc, charSrc+fStandardNumBytes[i], &fCopyBuffer[shift]);
    277 //              for (int j=0; j<fStandardNumBytes[i]; j++)
    278 //                      fCopyBuffer[shift+j] = static_cast<char*>(fStandardPointers[i])[fStandardNumBytes[i]-(j+1)];
    279271                shift+= fStandardNumBytes[i];   
    280272        }
     
    284276                         
    285277        //data copied to buffer, can write to fits
    286 //      int status = 0;
    287         //TODO check the status after the write operation
    288278        fits_write_tblbytes(fFile->fitsPointer(), fNumRows, 1, fTotalNumBytes, fCopyBuffer, &status);
    289279        if (status)
     
    291281                char text[30];//max length of cfitsio error strings (from doc)
    292282                fits_get_errstatus(status, text);
    293                 std::stringstream str;
     283                stringstream str;
    294284                str << "Error while writing FITS row in " << fFileName << ". Message: " << text << " [" << status << "]";
    295285                fMess->Error(str);     
    296286        }
    297         //This forces the writting of each row to the disk. Otherwise all rows are written when the file is closed.
    298         ///TODO check whether this consumes too much resources or not. If it does, flush every N write operations instead
    299 /*      try
    300         {
    301                 fFile->flush();
    302         }
    303         catch (CCfits::FitsError e)
    304         {
    305                 std::stringstream str;
    306                 str << "Error while flushing bytes to disk. File: " << fFileName << " reason: " << e.message();
    307                 fMess->Error(str);     
    308         }
    309 */}
     287}
    310288// --------------------------------------------------------------------------
    311289//
     
    335313
    336314// --------------------------------------------------------------------------
    337 //
     315//! Returns the size on the disk of the Fits file being written.
    338316int Fits::GetWrittenSize()
    339317{
  • trunk/FACT++/src/Fits.h

    r10725 r10741  
    1010class MessageImp;
    1111
     12using namespace std;
     13
    1214class Fits
    1315{
    1416        private:
    1517                ///The CCfits object to the FITS file
    16                 CCfits::FITS* fFile;
     18        CCfits::FITS* fFile;
    1719                ///Flag indicating whether the FITS object should be managed internally or not.
    1820                bool fOwner;
     
    2426                ///TODO make these variable static so that they are shared by every object.
    2527                ///TODO add also a static boolean to initialize these only once
    26                 std::vector<Description> fStandardColDesc;
     28                vector<Description> fStandardColDesc;
    2729                ///Format of the standard columns.
    28                 std::vector<std::string> fStandardFormats;
     30                vector<string> fStandardFormats;
    2931                ///the pointers to the standard variables
    30                 std::vector<void*> fStandardPointers;
     32                vector<void*> fStandardPointers;
    3133                ///the number of bytes taken by each standard variable
    32                 std::vector<int> fStandardNumBytes;
     34                vector<int> fStandardNumBytes;
    3335                ///the vector of data column names
    34                 std::vector<Description> fDataColDesc;
     36                vector<Description> fDataColDesc;
    3537                ///the data format of the data columns
    36                 std::vector<std::string> fDataFormats;
     38                vector<string> fDataFormats;
    3739                ///the pointer to the contiguous memory location where the data is stored (i.e. the dim data pointer)
    3840                void* fDataPointer;
     
    5153public:
    5254                ///Name of the openned file. For querying stats
    53                 std::string fFileName;
     55                string fFileName;
    5456private:
    5557                ///Keep track of number of opened fits
     
    8385               
    8486                ///Adds a column that exists in all FITS files
    85                 void AddStandardColumn(Description& desc, std::string dataFormat, void* dataPointer, long unsigned int numDataBytes);
     87                void AddStandardColumn(Description& desc, string dataFormat, void* dataPointer, long unsigned int numDataBytes);
    8688               
    8789                ///Adds columns specific to the service being logged.
    88                 void InitDataColumns(std::vector<Description> desc, std::vector<std::string>& dataFormat, void* dataPointer, int numDataBytes);
     90                void InitDataColumns(vector<Description> desc, vector<string>& dataFormat, void* dataPointer, int numDataBytes);
    8991
    9092                ///Opens a FITS file
    91         void Open(const std::string& fileName, const std::string& tableName, CCfits::FITS* file, int* fitsCounter, MessageImp* out);//std::ostream& out);
     93        void Open(const string& fileName, const string& tableName, CCfits::FITS* file, int* fitsCounter, MessageImp* out);//ostream& out);
    9294
    9395                ///Write one line of data. Use the given converter.
  • trunk/FACT++/src/dataLogger.cc

    r10739 r10741  
    1111  \dot
    1212  digraph datalogger {
    13                 node [shape=record, fontname=Helvetica, fontsize=10];
    14         e [label="Error" color="red"];
     13          node [shape=record, fontname=Helvetica, fontsize=10];
     14      e [label="Error" color="red"];
    1515   r [label="Ready"]
    1616   d [label="NightlyOpen"]
    1717   w [label="WaitingRun"]
    18         l [label="Logging"]
     18      l [label="Logging"]
    1919   b [label="BadNightlyconfig" color="red"]
    2020   c [label="BadRunConfig" color="red"]
     
    3737  }
    3838  \enddot
    39  
    40   @todo
    41         - Retrieve also the messages, not only the infos
    4239 */
    4340 //****************************************************************
     
    8279//Dim structures
    8380struct DataLoggerStats {
    84         long sizeWritten;
    85         long freeSpace;
    86         long writingRate;
     81    long sizeWritten;
     82    long freeSpace;
     83    long writingRate;
    8784};
    8885
    8986struct NumSubAndFitsType {
    90         int numSubscriptions;
    91         int numOpenFits;
     87    int numSubscriptions;
     88    int numOpenFits;
    9289};
    9390
    9491struct OpenFileToDim {
    95         int code;
    96         char fileName[FILENAME_MAX];
     92    int code;
     93    char fileName[FILENAME_MAX];
    9794};
    98 //For debugging DIM's services
    99 class MyService
     95
     96class DataLogger : public StateMachineDim, DimInfoHandler
    10097{
    10198public:
    102         MyService(){};
    103         MyService(std::string, std::string, void*, int){};
    104         MyService(std::string, const char*){};
    105         void updateService(){};
    106         void updateService(void*, int){};
    107         void setQuality(int){};
    108 };
    109 class DataLogger : public StateMachineDim, DimInfoHandler
    110 {
     99    /// The list of existing states specific to the DataLogger
     100    enum
     101    {
     102        kSM_NightlyOpen = 20, ///< Nightly file openned and writing
     103        kSM_WaitingRun = 30, ///< waiting for the run number to open the run file
     104        kSM_Logging = 40, ///< both files openned and writing
     105        kSM_BadNightlyConfig = 0x101, ///< the folder specified for Nightly logging does not exist or has bad permissions
     106        kSM_BadRunConfig = 0x102, ///<  the folder specified for the run logging does not exist or has wrong permissions or no run number
     107    } localstates_t;
     108   
     109    DataLogger(ostream &out);
     110    ~DataLogger();
     111   
     112private:
     113    //Define all the data structure specific to the DataLogger here
     114     /// ofstream for the NightlyLogfile
     115    ofstream fNightlyLogFile;
     116    /// ofstream for the run-specific Log file
     117    ofstream fRunLogFile;
     118
     119    /// ofstream for the Nightly report file
     120    ofstream fNightlyReportFile;
     121    /// ofstream for the run-specific report file
     122    ofstream fRunReportFile;
     123    /// base path of the Nightlyfile
     124    string fNightlyFileName;
     125    ///base path of the run file
     126    string fRunFileName;
     127    ///run number (-1 means no run number specified)
     128    int fRunNumber;
     129    ///previous run number. to check if changed while logging
     130    int fPreviousRunNumber;
     131    ///Current Service Quality
     132    int fQuality;
     133    ///Modified Julian Date
     134    double fMjD;
    111135public:
    112         /// The list of existing states specific to the DataLogger
    113         enum
    114         {
    115                 kSM_NightlyOpen = 20, ///< Nightly file openned and writing
    116                 kSM_WaitingRun = 30, ///< waiting for the run number to open the run file
    117                 kSM_Logging = 40, ///< both files openned and writing
    118                 kSM_BadNightlyConfig = 0x101, ///< the folder specified for Nightly logging does not exist or has bad permissions
    119                 kSM_BadRunConfig = 0x102, ///<  the folder specified for the run logging does not exist or has wrong permissions or no run number
    120         } localstates_t;
    121        
    122     DataLogger(std::ostream &out);
    123         ~DataLogger();
    124        
     136    ///Define all the static names
     137    static const char* fConfigDay;
     138    static const char* fConfigRun;
     139    static const char* fConfigRunNumber;
     140    static const char* fConfigLog;
     141    static const char* fTransStart;
     142    static const char* fTransStop;
     143    static const char* fTransStartRun;
     144    static const char* fTransStopRun;
     145    static const char* fTransReset;
     146    static const char* fTransWait;
     147    static const char* fRunNumberInfo; ///< This is the name of the dimInfo received to specify the run number. It must be updated once the final name will be defined
     148    static const char* fPrintCommand;
     149    static const char* fDebugOnOff;
     150    static const char* fStatsPeriod;
     151    static const char* fStartStopOpenedFiles;
     152    static const char* fStartStopNumSubsAndFits;
    125153private:
    126         //Define all the data structure specific to the DataLogger here
    127         /// ofstream for the NightlyLogfile
    128         std::ofstream fNightlyLogFile;
    129         /// ofstream for the run-specific Log file
    130         std::ofstream fRunLogFile;
    131 
    132         /// ofstream for the Nightly report file
    133         std::ofstream fNightlyReportFile;
    134         /// ofstream for the run-specific report file
    135         std::ofstream fRunReportFile;
    136         /// base path of the Nightlyfile
    137         std::string fNightlyFileName;
    138         ///base path of the run file
    139         std::string fRunFileName;
    140         ///run number (-1 means no run number specified)
    141         int fRunNumber;
    142         ///previous run number. to check if changed while logging
    143         int fPreviousRunNumber;
    144         ///Current Service Quality
    145         int fQuality;
    146         ///Modified Julian Date
    147         double fMjD;
    148 public:
    149         ///Define all the static names
    150         static const char* fConfigDay;
    151         static const char* fConfigRun;
    152         static const char* fConfigRunNumber;
    153         static const char* fConfigLog;
    154         static const char* fTransStart;
    155         static const char* fTransStop;
    156         static const char* fTransStartRun;
    157         static const char* fTransStopRun;
    158         static const char* fTransReset;
    159         static const char* fTransWait;
    160         static const char* fRunNumberInfo; ///< This is the name of the dimInfo received to specify the run number. It must be updated once the final name will be defined
    161         static const char* fPrintCommand;
    162         static const char* fDebugOnOff;
    163         static const char* fStatsPeriod;
    164         static const char* fStartStopOpenedFiles;
    165         static const char* fStartStopNumSubsAndFits;
     154    //overloading of DIM's infoHandler function
     155    void infoHandler();
     156   
     157    ///for obtaining the name of the existing services
     158    ServiceList fServiceList;
     159   
     160    ///A std pair to store both the DimInfo pointer and the corresponding outputted fits file
     161    struct SubscriptionType
     162    {
     163#ifdef HAVE_FITS
     164        ///Nightly FITS output file
     165        Fits    nightlyFile;
     166        ///run-specific FITS output file
     167        Fits    runFile;
     168#endif
     169        ///the actual dimInfo pointer
     170        DimStampedInfo* dimInfo;
     171        ///the converter for outputting the data according to the format
     172        Converter* fConv;
     173        ///the number of existing handlers to this structure.
     174        ///This is required otherwise I MUST handle the deleting of dimInfo outside from the destructor
     175        int* numCopies;
     176        void operator = (const SubscriptionType& other)
     177        {
     178#ifdef HAVE_FITS
     179            nightlyFile = other.nightlyFile;
     180            runFile = other.runFile;
     181#endif
     182            dimInfo = other.dimInfo;   
     183            numCopies = other.numCopies;
     184            fConv = other.fConv;
     185            (*numCopies)++;
     186        }
     187        SubscriptionType(const SubscriptionType& other)
     188        {
     189#ifdef HAVE_FITS
     190            nightlyFile = other.nightlyFile;
     191            runFile = other.runFile;
     192#endif
     193            dimInfo = other.dimInfo;
     194            numCopies = other.numCopies;
     195            fConv = other.fConv;
     196            (*numCopies)++;   
     197        }
     198        SubscriptionType(DimStampedInfo* info)
     199        {
     200            dimInfo = info;   
     201            fConv = NULL;
     202            numCopies = new int(1);
     203        }
     204        SubscriptionType()
     205        {
     206            dimInfo = NULL;
     207            fConv = NULL;
     208            numCopies = new int(1);
     209        }
     210        ~SubscriptionType()
     211        {
     212            if (numCopies)
     213            (*numCopies)--;
     214            if (numCopies)
     215            if (*numCopies < 1)
     216            {
     217                if (dimInfo)
     218                delete dimInfo;
     219#ifdef HAVE_FITS
     220                if (nightlyFile.IsOpen())
     221                    nightlyFile.Close();
     222                if (runFile.IsOpen())
     223                    runFile.Close();
     224#endif
     225                if (numCopies)   
     226                delete numCopies;
     227                delete fConv;
     228                fConv = NULL;
     229                dimInfo = NULL;
     230                numCopies = NULL;
     231            }
     232        }
     233    };
     234    typedef map<const string, map<string, SubscriptionType> > SubscriptionsListType;
     235    ///All the services to which we have subscribed to, sorted by server name.
     236    SubscriptionsListType fServiceSubscriptions;
     237
     238    ///Reporting method for the services info received
     239    void ReportPlease(DimInfo* I, SubscriptionType& sub); 
     240
     241    ///Configuration of the nightly file path
     242    int ConfigureNightlyFileName(const Event& evt);
     243    ///Configuration fo the file name
     244    int ConfigureRunFileName(const Event& evt);
     245    ///DEPREC - configuration of the run number
     246    int ConfigureRunNumber(const Event& evt);
     247    ///logging method for the messages
     248    int LogMessagePlease(const Event& evt);
     249    ///print the current state of the dataLogger
     250    int PrintStatePlease(const Event& evt);
     251    ///checks whether or not the current info being treated is a run number
     252    void CheckForRunNumber(DimInfo* I);
     253    /// start transition
     254    int StartPlease();
     255    ///from waiting to logging transition
     256    int StartRunPlease();
     257    /// from logging to waiting transition
     258    int StopRunPlease();
     259    ///stop and reset transition
     260    int GoToReadyPlease();
     261    ///from NightlyOpen to waiting transition
     262    int NightlyToWaitRunPlease();
     263#ifdef HAVE_FITS
     264    ///Open fits files
     265    void OpenFITSFilesPlease(SubscriptionType& sub);
     266    ///Write data to FITS files
     267    void WriteToFITS(SubscriptionType& sub);
     268    ///Allocate the buffers required for fits
     269    void AllocateFITSBuffers(SubscriptionType& sub);
     270    ///FITS file for runs grouping. only one, hence dealt with in the dataLogger itself
     271    CCfits::FITS* fRunFitsFile;
     272#endif//has_fits
     273public:   
     274    ///checks with fServiceList whether or not the services got updated
     275    bool CheckForServicesUpdate();
     276
     277private:   
     278    ///monitoring notification loop
     279    void ServicesMonitoring();
     280    ///services notification thread
     281    boost::thread fMonitoringThread;
     282    ///end of the monitoring
     283    bool fContinueMonitoring;
     284    ///required for accurate monitoring
     285    map<string, long> fFileSizesMap;
     286    string fFullNightlyLogFileName;
     287    string fFullNightlyReportFileName;
     288    string fFullRunLogFileName;
     289    string fFullRunReportFileName;
     290    long fBaseSizeNightly;
     291    long fPreviousSize;
     292    long fBaseSizeRun;
     293    ///Service for opened files
     294    DimDescribedService* fOpenedNightlyFiles;
     295    DimDescribedService* fOpenedRunFiles;
     296    DimDescribedService* fNumSubAndFits;
     297    NumSubAndFitsType fNumSubAndFitsData;
     298
     299    inline void NotifyOpenedFile(string name, int type, DimDescribedService* service);
     300
     301public:   
     302    bool SetConfiguration(Configuration& conf);
     303
    166304private:
    167         //overloading of DIM's infoHandler function
    168         void infoHandler();
    169        
    170         ///for obtaining the name of the existing services
    171         ServiceList fServiceList;
    172        
    173         ///A std pair to store both the DimInfo pointer and the corresponding outputted fits file
    174         struct SubscriptionType
    175         {
     305    set<string> fBlackList;
     306    set<string> fWhiteList;
     307    set<string> fGrouping;
     308    bool fHasBlackList;
     309    bool fHasWhiteList;
     310    bool fDebugIsOn;
     311    float fStatsPeriodDuration;
     312    bool fOpenedFilesIsOn;
     313    bool fNumSubAndFitsIsOn;
     314    //functions for controlling the services behavior
     315    int SetDebugOnOff(const Event& evt);
     316    int SetStatsPeriod(const Event& evt);
     317    int SetOpenedFilesOnOff(const Event& evt);
     318    int SetNumSubsAndFitsOnOff(const Event& evt);
     319    ///boolean to prevent DIM update while desctructing the dataLogger
     320    bool fDestructing;   
     321
     322    ///Small function for calculating the total size written so far
     323    void calculateTotalSizeWritten(DataLoggerStats& statVar, bool& shouldWarn, bool isPrinting);
     324
     325    ///vectors to keep track of opened Fits files, for grouping purposes.
     326    //This cannot be done otherwise, as services may disapear before the files are nicely closed. Hence which files were opened must be remembered.
     327    map<string, vector<string> > fOpenedRunFits;
     328    map<string, vector<string> > fOpenedNightlyFits;
     329    void CreateFitsGrouping(bool runGroup);
     330}; //DataLogger
     331
     332void DataLogger::calculateTotalSizeWritten(DataLoggerStats& statVar, bool& shouldWarn, bool isPrinting)
     333{
    176334#ifdef HAVE_FITS
    177                 ///Nightly FITS output file
    178                 Fits    nightlyFile;
    179                 ///run-specific FITS output file
    180                 Fits    runFile;
     335    if (isPrinting)
     336    {
     337        stringstream str;
     338        str.str("");
     339        str << "There are " << fNumSubAndFitsData.numOpenFits << " FITS files open:";
     340        Message(str.str());
     341    }
     342    SubscriptionsListType::iterator x;
     343    map<string, SubscriptionType>::iterator y;
     344///TODO the grouping file is dealt with several times. This should not be a problem but well, better to fix it I guess.
     345    for (x=fServiceSubscriptions.begin(); x != fServiceSubscriptions.end(); x++)
     346    {
     347        for (y=x->second.begin(); y != x->second.end(); y++)
     348        {
     349            if (y->second.runFile.IsOpen())
     350            {
     351                    fFileSizesMap[y->second.runFile.fFileName] = y->second.runFile.GetWrittenSize();
     352                    if (isPrinting)
     353                        Message("-> "+y->second.runFile.fFileName);
     354            }
     355            if (y->second.nightlyFile.IsOpen())
     356            {
     357                fFileSizesMap[y->second.nightlyFile.fFileName] = y->second.nightlyFile.GetWrittenSize();
     358                if (isPrinting)
     359                    Message("-> "+y->second.nightlyFile.fFileName);
     360            }
     361        }
     362    }
     363#else
     364    if (isPrinting)
     365        Message("FITS output disabled at compilation");
    181366#endif
    182                 ///the actual dimInfo pointer
    183                 DimStampedInfo* dimInfo;
    184                 ///the converter for outputting the data according to the format
    185                 Converter* fConv;
    186                 ///the number of existing handlers to this structure.
    187                 ///This is required otherwise I MUST handle the deleting of dimInfo outside from the destructor
    188                 int* numCopies;
    189                 void operator = (const SubscriptionType& other)
    190                 {
    191 #ifdef HAVE_FITS
    192                         nightlyFile = other.nightlyFile;
    193                         runFile = other.runFile;
    194 #endif
    195                         dimInfo = other.dimInfo;       
    196                         numCopies = other.numCopies;
    197                         fConv = other.fConv;
    198                         (*numCopies)++;
    199                 }
    200                 SubscriptionType(const SubscriptionType& other)
    201                 {
    202 #ifdef HAVE_FITS
    203                         nightlyFile = other.nightlyFile;
    204                         runFile = other.runFile;
    205 #endif
    206                         dimInfo = other.dimInfo;
    207                         numCopies = other.numCopies;
    208                         fConv = other.fConv;
    209                         (*numCopies)++;
    210                 }
    211                 SubscriptionType(DimStampedInfo* info)
    212                 {
    213                         dimInfo = info;
    214                         fConv = NULL;
    215                         numCopies = new int(1);
    216                 }
    217                 SubscriptionType()
    218                 {
    219                         dimInfo = NULL;
    220                         fConv = NULL;
    221                         numCopies = new int(1);
    222                 }
    223                 ~SubscriptionType()
    224                 {
    225                         if (numCopies)
    226                         (*numCopies)--;
    227                         if (numCopies)
    228                         if (*numCopies < 1)
    229                         {
    230                                 if (dimInfo)
    231                                 delete dimInfo;
    232 #ifdef HAVE_FITS
    233                                 if (nightlyFile.IsOpen())
    234                                         nightlyFile.Close();
    235                                 if (runFile.IsOpen())
    236                                         runFile.Close();
    237 #endif
    238                                 if (numCopies) 
    239                                 delete numCopies;
    240                                 delete fConv;
    241                                 fConv = NULL;
    242                                 dimInfo = NULL;
    243                                 numCopies = NULL;
    244                         }
    245                 }
    246         };
    247         typedef std::map<const std::string, std::map<std::string, SubscriptionType>> SubscriptionsListType;
    248         ///All the services to which we have subscribed to, sorted by server name.
    249         SubscriptionsListType fServiceSubscriptions;
    250 
    251         ///Reporting method for the services info received
    252         void ReportPlease(DimInfo* I, SubscriptionType& sub); 
    253 
    254         ///Configuration of the nightly file path
    255         int ConfigureNightlyFileName(const Event& evt);
    256         ///Configuration fo the file name
    257         int ConfigureRunFileName(const Event& evt);
    258         ///DEPREC - configuration of the run number
    259         int ConfigureRunNumber(const Event& evt);
    260         ///logging method for the messages
    261         int LogMessagePlease(const Event& evt);
    262         ///print the current state of the dataLogger
    263         int PrintStatePlease(const Event& evt);
    264         ///checks whether or not the current info being treated is a run number
    265         void CheckForRunNumber(DimInfo* I);
    266         /// start transition
    267         int StartPlease();
    268         ///from waiting to logging transition
    269         int StartRunPlease();
    270         /// from logging to waiting transition
    271         int StopRunPlease();
    272         ///stop and reset transition
    273         int GoToReadyPlease();
    274         ///from NightlyOpen to waiting transition
    275         int NightlyToWaitRunPlease();
    276 #ifdef HAVE_FITS
    277         ///Open fits files
    278         void OpenFITSFilesPlease(SubscriptionType& sub);
    279         ///Write data to FITS files
    280         void WriteToFITS(SubscriptionType& sub);
    281         ///Allocate the buffers required for fits
    282         void AllocateFITSBuffers(SubscriptionType& sub);
    283                
    284 #ifdef ONE_RUN_FITS_ONLY
    285         ///FITS file for runs. only one, hence dealt with in the dataLogger itself
    286         CCfits::FITS* fRunFitsFile;
    287 #endif //one_run_fits_only
    288 #endif//has_fits
    289 public:
    290         ///checks with fServiceList whether or not the services got updated
    291         bool CheckForServicesUpdate();
    292 
    293 private:       
    294         ///monitoring notification loop
    295         void ServicesMonitoring();
    296         ///services notification thread
    297         boost::thread fMonitoringThread;
    298         ///end of the monitoring
    299         bool fContinueMonitoring;
    300         ///required for accurate monitoring
    301         std::map<std::string, long> fFileSizesMap;
    302         std::string fFullNightlyLogFileName;
    303         std::string fFullNightlyReportFileName;
    304         std::string fFullRunLogFileName;
    305         std::string fFullRunReportFileName;
    306         long fBaseSizeNightly;
    307         long fPreviousSize;
    308         long fBaseSizeRun;
    309         ///Service for opened files
    310         DimDescribedService* fOpenedNightlyFiles;
    311         DimDescribedService* fOpenedRunFiles;
    312         DimDescribedService* fNumSubAndFits;
    313         NumSubAndFitsType fNumSubAndFitsData;
    314 
    315         inline void NotifyOpenedFile(std::string name, int type, DimDescribedService* service);
    316 
    317 public:
    318         bool SetConfiguration(Configuration& conf);
    319 
    320 private:
    321         std::set<std::string> fBlackList;
    322         std::set<std::string> fWhiteList;
    323         bool fHasBlackList;
    324         bool fHasWhiteList;
    325         bool fDebugIsOn;
    326         float fStatsPeriodDuration;
    327         bool fOpenedFilesIsOn;
    328         bool fNumSubAndFitsIsOn;
    329         //functions for controlling the services behavior
    330         int SetDebugOnOff(const Event& evt);
    331         int SetStatsPeriod(const Event& evt);
    332         int SetOpenedFilesOnOff(const Event& evt);
    333         int SetNumSubsAndFitsOnOff(const Event& evt);
    334         ///boolean to prevent DIM update while desctructing the dataLogger
    335         bool fDestructing;     
    336 
    337         ///Small function for calculating the total size written so far
    338         void calculateTotalSizeWritten(DataLoggerStats& statVar, bool& shouldWarn, bool isPrinting);
    339 
    340         ///vectors to keep track of opened Fits files, for grouping purposes.
    341         //This cannot be done otherwise, as services may disapear before the files are nicely closed. Hence which files were opened must be remembered.
    342         map<string, string> fOpenedRunFits;
    343         map<string, string> fOpenedNightlyFits;
    344         void CreateFitsGrouping(bool runGroup);
    345 }; //DataLogger
    346 
    347 void DataLogger::calculateTotalSizeWritten(DataLoggerStats& statVar, bool& shouldWarn, bool isPrinting)
    348 {
    349 #ifdef HAVE_FITS
    350         if (isPrinting)
    351         {
    352                 stringstream str;
    353                 str.str("");
    354                 str << "There are " << fNumSubAndFitsData.numOpenFits << " FITS files open:";
    355                 Message(str.str());
    356         }
    357         SubscriptionsListType::iterator x;
    358         std::map<std::string, SubscriptionType>::iterator y;
    359         bool runFileDone = false;
    360         for (x=fServiceSubscriptions.begin(); x != fServiceSubscriptions.end(); x++)
    361         {
    362                 for (y=x->second.begin(); y != x->second.end(); y++)
    363                 {
    364                         if (y->second.runFile.IsOpen() && !runFileDone)
    365                         {
    366                                         fFileSizesMap[y->second.runFile.fFileName] = y->second.runFile.GetWrittenSize();
    367                                         if (isPrinting)
    368                                                 Message("-> "+y->second.runFile.fFileName);
    369 #ifdef ONE_FITS_ONLY
    370                                         runFileDone = true;
    371 #endif
    372                         }
    373                         if (y->second.nightlyFile.IsOpen())
    374                         {
    375                                 fFileSizesMap[y->second.nightlyFile.fFileName] = y->second.nightlyFile.GetWrittenSize();
    376                                 if (isPrinting)
    377                                         Message("-> "+y->second.nightlyFile.fFileName);
    378                         }
    379                 }
    380         }
    381 #else
    382         if (isPrinting)
    383                 Message("FITS output disabled at compilation");
    384 #endif
    385         struct stat st;
    386         //gather log and report files sizes on disk
    387         if (fNightlyLogFile.is_open())
    388         {
    389                 stat(fFullNightlyLogFileName.c_str(), &st);
    390                 fFileSizesMap[fFullNightlyLogFileName] = st.st_size;
    391         }
    392         if (fNightlyReportFile.is_open())
    393         {
    394                 stat(fFullNightlyReportFileName.c_str(), &st);
    395                 fFileSizesMap[fFullNightlyReportFileName] = st.st_size;
    396         }
    397         if (fRunLogFile.is_open())
    398         {
    399                 stat(fFullRunLogFileName.c_str(), &st);
    400                 fFileSizesMap[fFullRunLogFileName] = st.st_size;
    401         }
    402         if (fRunReportFile.is_open())
    403         {
    404                 stat(fFullRunReportFileName.c_str(), &st);
    405                 fFileSizesMap[fFullRunReportFileName] = st.st_size;
    406         }
    407         struct statvfs vfs;
    408         if (!statvfs(fNightlyFileName.c_str(), &vfs))
    409         {
    410                 statVar.freeSpace = vfs.f_bsize*vfs.f_bavail;
    411                 shouldWarn = false;
    412         }
    413         else
    414         {
    415                 stringstream str;
    416                 str.str("");
    417                 str << "Unable to retrieve stats for " << fNightlyFileName << ". Reason: " << strerror(errno) << " [" << errno << "]";
    418                 if (!shouldWarn)
    419                         Error(str);
    420                 shouldWarn = true;
    421                 statVar.freeSpace = -1;
    422         }
    423         //sum up all the file sizes. past and present
    424         statVar.sizeWritten = 0;
    425         for (std::map<std::string, long>::iterator it=fFileSizesMap.begin(); it != fFileSizesMap.end();  it++)
    426                 statVar.sizeWritten += it->second;
    427         statVar.sizeWritten -= fBaseSizeNightly;
    428         statVar.sizeWritten -= fBaseSizeRun;
     367    struct stat st;
     368    //gather log and report files sizes on disk
     369    if (fNightlyLogFile.is_open())
     370    {
     371        stat(fFullNightlyLogFileName.c_str(), &st);
     372        fFileSizesMap[fFullNightlyLogFileName] = st.st_size;
     373    }
     374    if (fNightlyReportFile.is_open())
     375    {
     376        stat(fFullNightlyReportFileName.c_str(), &st);
     377        fFileSizesMap[fFullNightlyReportFileName] = st.st_size;
     378    }
     379    if (fRunLogFile.is_open())
     380    {
     381        stat(fFullRunLogFileName.c_str(), &st);
     382        fFileSizesMap[fFullRunLogFileName] = st.st_size;
     383    }
     384    if (fRunReportFile.is_open())
     385    {
     386        stat(fFullRunReportFileName.c_str(), &st);
     387        fFileSizesMap[fFullRunReportFileName] = st.st_size;
     388    }
     389    struct statvfs vfs;
     390    if (!statvfs(fNightlyFileName.c_str(), &vfs))
     391    {
     392        statVar.freeSpace = vfs.f_bsize*vfs.f_bavail;
     393        shouldWarn = false;
     394    }
     395    else
     396    {
     397        stringstream str;
     398        str.str("");
     399        str << "Unable to retrieve stats for " << fNightlyFileName << ". Reason: " << strerror(errno) << " [" << errno << "]";
     400        if (!shouldWarn)
     401            Error(str);
     402        shouldWarn = true;
     403        statVar.freeSpace = -1;
     404    }
     405    //sum up all the file sizes. past and present
     406    statVar.sizeWritten = 0;
     407    for (map<string, long>::iterator it=fFileSizesMap.begin(); it != fFileSizesMap.end();  it++)
     408        statVar.sizeWritten += it->second;
     409    statVar.sizeWritten -= fBaseSizeNightly;
     410    statVar.sizeWritten -= fBaseSizeRun;
    429411}
    430412//static members initialization
     
    449431void DataLogger::ServicesMonitoring()
    450432{
    451                 DataLoggerStats statVar;
    452                 statVar.sizeWritten = 0;
    453                 statVar.freeSpace = 0;
    454                 statVar.writingRate = 0;
    455 
    456                 struct statvfs vfs;
    457                 if (!statvfs(fNightlyFileName.c_str(), &vfs))
    458                         statVar.freeSpace = vfs.f_bsize*vfs.f_bavail;
    459                 else
    460                         statVar.freeSpace = -1;
    461 
    462                 DimDescribedService srvc ("DATA_LOGGER/STATS", "X:3", statVar, "Add description here");
    463                 fPreviousSize = 0;
    464                 bool statWarning = false;
    465                 //loop-wait for broadcast
    466                 while (fContinueMonitoring)
    467                 {
    468                         if (fStatsPeriodDuration == 0.0f)
    469                         {
    470                                 sleep(0.1f);
    471                                 continue;
    472                         }
    473                         else
    474                                 sleep(fStatsPeriodDuration);
    475                         //update the fits files sizes
    476                         calculateTotalSizeWritten(statVar, statWarning, false);
    477                         if (fStatsPeriodDuration == 0.0f)
    478                                 continue;
    479                         statVar.writingRate = (statVar.sizeWritten - fPreviousSize)/fStatsPeriodDuration; 
    480 
    481                         fPreviousSize = statVar.sizeWritten;
    482                         if (statVar.writingRate != 0) //if data has been written
    483                         {
    484                                 srvc.updateService();
    485                                 if(fDebugIsOn)
    486                                 {
    487                                         stringstream str;
    488                                         str << "Size written: " << statVar.sizeWritten/1024 << " KB; writting rate: ";
    489                                         str << statVar.writingRate/1024 << " KB/s; free space: ";
    490                                         str << statVar.freeSpace/(1024*1024) << " MB";
    491                                         Debug(str.str());
    492                                 }
    493                         }
    494                 }
     433        DataLoggerStats statVar;
     434        statVar.sizeWritten = 0;
     435        statVar.freeSpace = 0;
     436        statVar.writingRate = 0;
     437
     438        struct statvfs vfs;
     439        if (!statvfs(fNightlyFileName.c_str(), &vfs))
     440            statVar.freeSpace = vfs.f_bsize*vfs.f_bavail;
     441        else
     442            statVar.freeSpace = -1;
     443
     444        DimDescribedService srvc ("DATA_LOGGER/STATS", "X:3", statVar, "Add description here");
     445        fPreviousSize = 0;
     446        bool statWarning = false;
     447        //loop-wait for broadcast
     448        while (fContinueMonitoring)
     449        {
     450            if (fStatsPeriodDuration == 0.0f)
     451            {
     452                sleep(0.1f);
     453                continue;
     454            }
     455            else
     456                sleep(fStatsPeriodDuration);
     457            //update the fits files sizes
     458            calculateTotalSizeWritten(statVar, statWarning, false);
     459            if (fStatsPeriodDuration == 0.0f)
     460                continue;
     461            statVar.writingRate = (statVar.sizeWritten - fPreviousSize)/fStatsPeriodDuration; 
     462
     463            fPreviousSize = statVar.sizeWritten;
     464            if (statVar.writingRate != 0) //if data has been written
     465            {
     466                srvc.updateService();
     467                if(fDebugIsOn)
     468                {
     469                    stringstream str;
     470                    str << "Size written: " << statVar.sizeWritten/1024 << " KB; writting rate: ";
     471                    str << statVar.writingRate/1024 << " KB/s; free space: ";
     472                    str << statVar.freeSpace/(1024*1024) << " MB";
     473                    Debug(str.str());
     474                }
     475            }
     476        }
    495477}
    496478
     
    503485//!Setup the allows states, configs and transitions for the data logger
    504486//
    505 DataLogger::DataLogger(std::ostream &out) : StateMachineDim(out, "DATA_LOGGER")
     487DataLogger::DataLogger(ostream &out) : StateMachineDim(out, "DATA_LOGGER")
    506488{
    507489    dic_disable_padding();
    508490    dis_disable_padding();
    509                 //initialize member data
    510                 fNightlyFileName = ".";
    511                 fRunFileName = ".";
    512                 fRunNumber = -1;
    513                 fPreviousRunNumber = fRunNumber;
     491    //initialize member data
     492    fNightlyFileName = ".";
     493    fRunFileName = ".";
     494    fRunNumber = -1;
     495    fPreviousRunNumber = fRunNumber;
    514496#ifdef HAVE_FITS
    515 #ifdef ONE_RUN_FITS_ONLY
    516                 fRunFitsFile = NULL;
     497    fRunFitsFile = NULL;
    517498#endif
    518 #endif
    519 
    520                 //Give a name to this machine's specific states
    521                 AddStateName(kSM_NightlyOpen,      "NightlyFileOpen",  "The summary files for the night are open.");
    522                 AddStateName(kSM_WaitingRun,       "WaitForRun",       "The summary files for the night are open and we wait for a run to be started.");
    523                 AddStateName(kSM_Logging,          "Logging",          "The summary files for the night and the files for a single run are open.");
    524                 AddStateName(kSM_BadNightlyConfig, "ErrNightlyFolder", "The folder for the nighly summary files is invalid.");
    525                 AddStateName(kSM_BadRunConfig,     "ErrRunFolder",     "The folder for the run files is invalid.");
    526 
    527                 /*Add the possible transitions for this machine*/
    528                 AddEvent(kSM_NightlyOpen, fTransStart, kSM_Ready, kSM_BadNightlyConfig)
    529                     (boost::bind(&DataLogger::StartPlease, this))
    530                     ("Start the nightly logging. Nightly file location must be specified already");
    531 
    532                 AddEvent(kSM_Ready, fTransStop, kSM_NightlyOpen, kSM_WaitingRun, kSM_Logging)
    533                     (boost::bind(&DataLogger::GoToReadyPlease, this))
    534                     ("Stop all data logging, close all files.");
    535 
    536                 AddEvent(kSM_Logging, fTransStartRun, kSM_WaitingRun, kSM_BadRunConfig)
    537                     (boost::bind(&DataLogger::StartRunPlease, this))
    538                     ("Start the run logging. Run file location must be specified already.");
    539 
    540                 AddEvent(kSM_WaitingRun, fTransStopRun, kSM_Logging)
    541                     (boost::bind(&DataLogger::StopRunPlease, this))
    542                     ("Wait for a run to be started, open run-files as soon as a run number arrives.");
    543 
    544                 AddEvent(kSM_Ready, fTransReset, kSM_Error, kSM_BadNightlyConfig, kSM_BadRunConfig, kSM_Error)
    545                     (boost::bind(&DataLogger::GoToReadyPlease, this))
    546                     ("Transition to exit error states. Closes the nightly file if already opened.");
    547 
    548                 AddEvent(kSM_WaitingRun, fTransWait, kSM_NightlyOpen)
    549                     (boost::bind(&DataLogger::NightlyToWaitRunPlease, this));
    550 
    551                 /*Add the possible configurations for this machine*/
    552                 AddEvent(fConfigDay, "C", kSM_Ready, kSM_BadNightlyConfig)
    553                     (boost::bind(&DataLogger::ConfigureNightlyFileName, this, _1))
    554                     ("Configure the folder for the nightly files."
    555                      "|Path[string]:Absolute or relative path name where the nightly files should be stored.");
    556 
    557                 AddEvent(fConfigRun, "C", kSM_Ready, kSM_BadNightlyConfig, kSM_NightlyOpen, kSM_WaitingRun, kSM_BadRunConfig)
    558                     (boost::bind(&DataLogger::ConfigureRunFileName, this, _1))
    559                     ("Configure the folder for the run files."
    560                      "|Path[string]:Absolute or relative path name where the run files should be stored.");
    561 
    562                 AddEvent(fConfigRunNumber, "I", kSM_Ready, kSM_BadNightlyConfig, kSM_NightlyOpen, kSM_WaitingRun, kSM_BadRunConfig)
    563                     (boost::bind(&DataLogger::ConfigureRunNumber, this, _1))
    564                     ("configure the run number. cannot be done in logging state");
    565 
    566                 //Provide a logging command
    567                 //I get the feeling that I should be going through the EventImp
    568                 //instead of DimCommand directly, mainly because the commandHandler
    569                 //is already done in StateMachineImp.cc
    570                 //Thus I'll simply add a configuration, which I will treat as the logging command
    571                 AddEvent(fConfigLog, "C", kSM_NightlyOpen, kSM_Logging, kSM_WaitingRun, kSM_BadRunConfig)
    572                     (boost::bind(&DataLogger::LogMessagePlease, this, _1))
    573                     ("Log a single message to the log-files."
    574                      "|Message[string]:Message to be logged.");
    575                
    576                 //Provide a print command
    577                 stringstream str;
    578                 str <<  kSM_Ready << " " << kSM_NightlyOpen << " " << kSM_WaitingRun << " " << kSM_Logging << " " << kSM_BadNightlyConfig;
    579                 str << " " << kSM_BadRunConfig;
    580 
    581                                 AddEvent(fPrintCommand, str.str().c_str(), "")
    582 //                AddEvent(fPrintCommand, kSM_NightlyOpen, kSM_Logging, kSM_WaitingRun, kSM_BadNightlyConfig, kSM_BadRunConfig)
    583                     (boost::bind(&DataLogger::PrintStatePlease, this, _1))
    584                     ("Print information about the internal status of the data logger.");
    585 
    586                 fServiceList.SetHandler(this);
    587                 CheckForServicesUpdate();
    588 
    589                 //start the monitoring service
    590                 fContinueMonitoring = true;
    591                 fMonitoringThread = boost::thread(boost::bind(&DataLogger::ServicesMonitoring, this));
    592                 fBaseSizeNightly = 0;
    593                 fBaseSizeRun = 0;
    594                 OpenFileToDim fToDim;
    595                 fToDim.code = 0;
    596                 fToDim.fileName[0] = '\0';
    597 
    598                 fOpenedNightlyFiles = new DimDescribedService(GetName() + "/FILENAME_NIGHTLY", "I:1;C", fToDim,
    599                                                               "Path and base name which is used to compile the filenames for the nightly files."
    600                                                               "|Type[int]:type of open files (1=log, 2=rep, 4=fits)"
    601                                                               "|Name[string]:path and base file name");
    602 
    603                 fOpenedRunFiles = new DimDescribedService(GetName() + "/FILENAME_RUN", "I:1;C", fToDim,
    604                                                           "Path and base name which is used to compile the filenames for the run files."
    605                                                           "|Type[int]:type of open files (1=log, 2=rep, 4=fits)"
    606                                                           "|Name[string]:path and base file name");
    607 
    608                 fNumSubAndFitsData.numSubscriptions = 0;
    609                 fNumSubAndFitsData.numOpenFits = 0;
    610                 fNumSubAndFits = new DimDescribedService(GetName() + "/NUM_SUBS", "I:2", fNumSubAndFitsData,
    611                                                          "Shows number of services to which the data logger is currently subscribed and the total number of open files."
    612                                                          "|Subscriptions[int]:number of dim services to which the data logger is currently subscribed."
    613                                                          "|NumOpenFiles[int]:number of files currently open by the data logger");
    614 
    615         //black/white list
    616         fHasBlackList = false;
    617         fHasWhiteList = false;
    618                 fBlackList.clear();
    619                 fWhiteList.clear();
    620                 //services parameters
    621                 fDebugIsOn = false;
    622                 fStatsPeriodDuration = 1.0f;
    623                 fOpenedFilesIsOn = true;
    624                 fNumSubAndFitsIsOn = true;
    625 
    626                 //provide services control commands
    627                 AddEvent(fDebugOnOff, "B:1", kSM_NightlyOpen, kSM_Logging, kSM_WaitingRun, kSM_Ready)
    628                     (boost::bind(&DataLogger::SetDebugOnOff, this, _1))
    629                     ("Switch debug mode on off. Debug mode prints ifnormation about every service written to a file."
    630                      "|Enable[bool]:Enable of disable debuig mode (yes/no).");
    631 
    632                 AddEvent(fStatsPeriod, "F", kSM_NightlyOpen, kSM_Logging, kSM_WaitingRun, kSM_Ready)
    633                     (boost::bind(&DataLogger::SetStatsPeriod, this, _1))
    634                     ("Interval in which the data-logger statitistics service (STATS) is updated."
    635                      "Interval[s]:Floating point value in seconds.");
    636 
    637                 AddEvent(fStartStopOpenedFiles, "B:1", kSM_NightlyOpen, kSM_Logging, kSM_WaitingRun, kSM_Ready)
    638                     (boost::bind(&DataLogger::SetOpenedFilesOnOff ,this, _1))
    639                     ("Can be used to switch the service off which distributes information about the open files.");
    640 
    641                 AddEvent(fStartStopNumSubsAndFits, "B:1", kSM_NightlyOpen, kSM_Logging, kSM_WaitingRun, kSM_Ready)
    642                     (boost::bind(&DataLogger::SetNumSubsAndFitsOnOff, this, _1))
    643                     ("Can be used to switch the service off which distributes information about the number of subscriptions and open files.");
    644 
    645                 fDestructing = false;
    646                 if(fDebugIsOn)
    647                 {
    648                     Debug("DataLogger Init Done.");
    649                 }
     499
     500     //Give a name to this machine's specific states
     501     AddStateName(kSM_NightlyOpen,      "NightlyFileOpen",  "The summary files for the night are open.");
     502     AddStateName(kSM_WaitingRun,       "WaitForRun",       "The summary files for the night are open and we wait for a run to be started.");
     503     AddStateName(kSM_Logging,          "Logging",          "The summary files for the night and the files for a single run are open.");
     504     AddStateName(kSM_BadNightlyConfig, "ErrNightlyFolder", "The folder for the nighly summary files is invalid.");
     505     AddStateName(kSM_BadRunConfig,     "ErrRunFolder",     "The folder for the run files is invalid.");
     506
     507     /*Add the possible transitions for this machine*/
     508     AddEvent(kSM_NightlyOpen, fTransStart, kSM_Ready, kSM_BadNightlyConfig)
     509             (boost::bind(&DataLogger::StartPlease, this))
     510             ("Start the nightly logging. Nightly file location must be specified already");
     511
     512     AddEvent(kSM_Ready, fTransStop, kSM_NightlyOpen, kSM_WaitingRun, kSM_Logging)
     513             (boost::bind(&DataLogger::GoToReadyPlease, this))
     514             ("Stop all data logging, close all files.");
     515
     516     AddEvent(kSM_Logging, fTransStartRun, kSM_WaitingRun, kSM_BadRunConfig)
     517             (boost::bind(&DataLogger::StartRunPlease, this))
     518             ("Start the run logging. Run file location must be specified already.");
     519
     520     AddEvent(kSM_WaitingRun, fTransStopRun, kSM_Logging)
     521             (boost::bind(&DataLogger::StopRunPlease, this))
     522             ("Wait for a run to be started, open run-files as soon as a run number arrives.");
     523
     524     AddEvent(kSM_Ready, fTransReset, kSM_Error, kSM_BadNightlyConfig, kSM_BadRunConfig, kSM_Error)
     525             (boost::bind(&DataLogger::GoToReadyPlease, this))
     526             ("Transition to exit error states. Closes the nightly file if already opened.");
     527
     528     AddEvent(kSM_WaitingRun, fTransWait, kSM_NightlyOpen)
     529             (boost::bind(&DataLogger::NightlyToWaitRunPlease, this));
     530
     531     /*Add the possible configurations for this machine*/
     532     AddEvent(fConfigDay, "C", kSM_Ready, kSM_BadNightlyConfig)
     533             (boost::bind(&DataLogger::ConfigureNightlyFileName, this, _1))
     534             ("Configure the folder for the nightly files."
     535              "|Path[string]:Absolute or relative path name where the nightly files should be stored.");
     536
     537     AddEvent(fConfigRun, "C", kSM_Ready, kSM_BadNightlyConfig, kSM_NightlyOpen, kSM_WaitingRun, kSM_BadRunConfig)
     538             (boost::bind(&DataLogger::ConfigureRunFileName, this, _1))
     539             ("Configure the folder for the run files."
     540              "|Path[string]:Absolute or relative path name where the run files should be stored.");
     541
     542     AddEvent(fConfigRunNumber, "I", kSM_Ready, kSM_BadNightlyConfig, kSM_NightlyOpen, kSM_WaitingRun, kSM_BadRunConfig)
     543             (boost::bind(&DataLogger::ConfigureRunNumber, this, _1))
     544             ("configure the run number. cannot be done in logging state");
     545
     546     //Provide a logging command
     547     //I get the feeling that I should be going through the EventImp
     548     //instead of DimCommand directly, mainly because the commandHandler
     549     //is already done in StateMachineImp.cc
     550     //Thus I'll simply add a configuration, which I will treat as the logging command
     551     AddEvent(fConfigLog, "C", kSM_NightlyOpen, kSM_Logging, kSM_WaitingRun, kSM_BadRunConfig)
     552             (boost::bind(&DataLogger::LogMessagePlease, this, _1))
     553             ("Log a single message to the log-files."
     554              "|Message[string]:Message to be logged.");
     555       
     556     //Provide a print command
     557     stringstream str;
     558     str <<     kSM_Ready << " " << kSM_NightlyOpen << " " << kSM_WaitingRun << " " << kSM_Logging << " " << kSM_BadNightlyConfig;
     559     str << " " << kSM_BadRunConfig;
     560     AddEvent(fPrintCommand, str.str().c_str(), "")
     561             (boost::bind(&DataLogger::PrintStatePlease, this, _1))
     562             ("Print information about the internal status of the data logger.");
     563
     564     fServiceList.SetHandler(this);
     565     CheckForServicesUpdate();
     566
     567     //start the monitoring service
     568     fContinueMonitoring = true;
     569     fMonitoringThread = boost::thread(boost::bind(&DataLogger::ServicesMonitoring, this));
     570     fBaseSizeNightly = 0;
     571     fBaseSizeRun = 0;
     572     OpenFileToDim fToDim;
     573     fToDim.code = 0;
     574     fToDim.fileName[0] = '\0';
     575
     576     fOpenedNightlyFiles = new DimDescribedService(GetName() + "/FILENAME_NIGHTLY", "I:1;C", fToDim,
     577                               "Path and base name which is used to compile the filenames for the nightly files."
     578                               "|Type[int]:type of open files (1=log, 2=rep, 4=fits)"
     579                               "|Name[string]:path and base file name");
     580
     581     fOpenedRunFiles = new DimDescribedService(GetName() + "/FILENAME_RUN", "I:1;C", fToDim,
     582                               "Path and base name which is used to compile the filenames for the run files."
     583                               "|Type[int]:type of open files (1=log, 2=rep, 4=fits)"
     584                               "|Name[string]:path and base file name");
     585
     586     fNumSubAndFitsData.numSubscriptions = 0;
     587     fNumSubAndFitsData.numOpenFits = 0;
     588     fNumSubAndFits = new DimDescribedService(GetName() + "/NUM_SUBS", "I:2", fNumSubAndFitsData,
     589                               "Shows number of services to which the data logger is currently subscribed and the total number of open files."
     590                               "|Subscriptions[int]:number of dim services to which the data logger is currently subscribed."
     591                               "|NumOpenFiles[int]:number of files currently open by the data logger");
     592
     593     //black/white list
     594     fHasBlackList = false;
     595     fHasWhiteList = false;
     596     fBlackList.clear();
     597     fWhiteList.clear();
     598     //services parameters
     599     fDebugIsOn = false;
     600     fStatsPeriodDuration = 1.0f;
     601     fOpenedFilesIsOn = true;
     602     fNumSubAndFitsIsOn = true;
     603
     604     //provide services control commands
     605     AddEvent(fDebugOnOff, "B:1", kSM_NightlyOpen, kSM_Logging, kSM_WaitingRun, kSM_Ready)
     606             (boost::bind(&DataLogger::SetDebugOnOff, this, _1))
     607             ("Switch debug mode on off. Debug mode prints ifnormation about every service written to a file."
     608              "|Enable[bool]:Enable of disable debuig mode (yes/no).");
     609
     610     AddEvent(fStatsPeriod, "F", kSM_NightlyOpen, kSM_Logging, kSM_WaitingRun, kSM_Ready)
     611             (boost::bind(&DataLogger::SetStatsPeriod, this, _1))
     612             ("Interval in which the data-logger statitistics service (STATS) is updated."
     613              "Interval[s]:Floating point value in seconds.");
     614
     615     AddEvent(fStartStopOpenedFiles, "B:1", kSM_NightlyOpen, kSM_Logging, kSM_WaitingRun, kSM_Ready)
     616              (boost::bind(&DataLogger::SetOpenedFilesOnOff ,this, _1))
     617              ("Can be used to switch the service off which distributes information about the open files.");
     618
     619     AddEvent(fStartStopNumSubsAndFits, "B:1", kSM_NightlyOpen, kSM_Logging, kSM_WaitingRun, kSM_Ready)
     620             (boost::bind(&DataLogger::SetNumSubsAndFitsOnOff, this, _1))
     621             ("Can be used to switch the service off which distributes information about the number of subscriptions and open files.");
     622
     623     fDestructing = false;
     624     if(fDebugIsOn)
     625     {
     626         Debug("DataLogger Init Done.");
     627     }
    650628}
    651629// --------------------------------------------------------------------------
     
    653631//! Checks for changes in the existing services.
    654632//! Any new service will be added to the service list, while the ones which disappeared are removed.
    655 //! @todo
    656 //!     add the configuration (using the conf class ?)
    657633//
    658634//FIXME The service must be udpated so that I get the first notification. This should not be
    659635bool DataLogger::CheckForServicesUpdate()
    660636{
    661         bool serviceUpdated = false;
    662         //get the current server list
    663         const std::vector<std::string> serverList = fServiceList.GetServerList();
    664         //first let's remove the servers that may have disapeared
    665         //can't treat the erase on maps the same way as for vectors. Do it the safe way instead
    666         std::vector<std::string> toBeDeleted;
    667         for (SubscriptionsListType::iterator cListe = fServiceSubscriptions.begin(); cListe != fServiceSubscriptions.end(); cListe++)
    668         {
    669                 std::vector<std::string>::const_iterator givenServers;
    670                 for (givenServers=serverList.begin(); givenServers!= serverList.end(); givenServers++)
    671                         if (cListe->first == *givenServers)
    672                                 break;
    673                 if (givenServers == serverList.end())//server vanished. Remove it
    674                 {       
    675                         toBeDeleted.push_back(cListe->first);
    676                         serviceUpdated = true;
    677                 }
    678                        
    679         }
    680         for (std::vector<std::string>::const_iterator it = toBeDeleted.begin(); it != toBeDeleted.end(); it++)
    681                 fServiceSubscriptions.erase(*it);
    682         //now crawl through the list of servers, and see if there was some updates
    683         for (std::vector<std::string>::const_iterator i=serverList.begin(); i!=serverList.end();i++)
    684         {
    685                 //skip the two de-fact excluded services
    686                 //Dim crashes if the publisher subscribes to its own service. This sounds weird, I agree.
    687                 if ((i->find("DIS_DNS") != std::string::npos) ||
    688                     (i->find("DATA_LOGGER") != std::string::npos))
    689                         continue;
    690                 //find the current server in our subscription list     
    691                 SubscriptionsListType::iterator cSubs = fServiceSubscriptions.find(*i);
    692                 //get the service list of the current server
    693                 std::vector<std::string> cServicesList = fServiceList.GetServiceList(*i);
    694                 if (cSubs != fServiceSubscriptions.end())//if the current server already is in our subscriptions
    695                 {                                                                                //then check and update our list of subscriptions
    696                         //first, remove the services that may have dissapeared.
    697                         std::map<std::string, SubscriptionType>::iterator serverSubs;
    698                         std::vector<std::string>::const_iterator givenSubs;
    699                         toBeDeleted.clear();
    700                         for (serverSubs=cSubs->second.begin(); serverSubs != cSubs->second.end(); serverSubs++)
    701                         {
    702                                 for (givenSubs = cServicesList.begin(); givenSubs != cServicesList.end(); givenSubs++)
    703                                         if (serverSubs->first == *givenSubs)
    704                                                 break;
    705                                 if (givenSubs == cServicesList.end())
    706                                 {
    707                                         toBeDeleted.push_back(serverSubs->first);
    708                                         serviceUpdated = true;
    709                                 }       
    710                         }
    711                         for (std::vector<std::string>::const_iterator it = toBeDeleted.begin(); it != toBeDeleted.end(); it++)
    712                                 cSubs->second.erase(*it);
    713                         //now check for new services
    714                         for (givenSubs = cServicesList.begin(); givenSubs != cServicesList.end(); givenSubs++)
    715                         {
    716                                 if (*givenSubs == "SERVICE_LIST")
    717                                         continue;
    718 
    719                                 if (fHasWhiteList && (fWhiteList.find(*i + "/") == fWhiteList.end()) &&
     637    bool serviceUpdated = false;
     638    //get the current server list
     639    const vector<string> serverList = fServiceList.GetServerList();
     640    //first let's remove the servers that may have disapeared
     641    //can't treat the erase on maps the same way as for vectors. Do it the safe way instead
     642    vector<string> toBeDeleted;
     643    for (SubscriptionsListType::iterator cListe = fServiceSubscriptions.begin(); cListe != fServiceSubscriptions.end(); cListe++)
     644    {
     645        vector<string>::const_iterator givenServers;
     646        for (givenServers=serverList.begin(); givenServers!= serverList.end(); givenServers++)
     647            if (cListe->first == *givenServers)
     648                break;
     649        if (givenServers == serverList.end())//server vanished. Remove it
     650        {   
     651            toBeDeleted.push_back(cListe->first);
     652            serviceUpdated = true;
     653        }
     654    }
     655    for (vector<string>::const_iterator it = toBeDeleted.begin(); it != toBeDeleted.end(); it++)
     656        fServiceSubscriptions.erase(*it);
     657    //now crawl through the list of servers, and see if there was some updates
     658    for (vector<string>::const_iterator i=serverList.begin(); i!=serverList.end();i++)
     659    {
     660        //skip the two de-fact excluded services
     661        //Dim crashes if the publisher subscribes to its own service. This sounds weird, I agree.
     662        if ((i->find("DIS_DNS") != string::npos) ||
     663            (i->find("DATA_LOGGER") != string::npos))
     664            continue;
     665        //find the current server in our subscription list   
     666        SubscriptionsListType::iterator cSubs = fServiceSubscriptions.find(*i);
     667        //get the service list of the current server
     668        vector<string> cServicesList = fServiceList.GetServiceList(*i);
     669        if (cSubs != fServiceSubscriptions.end())//if the current server already is in our subscriptions
     670        {                                         //then check and update our list of subscriptions
     671            //first, remove the services that may have dissapeared.
     672            map<string, SubscriptionType>::iterator serverSubs;
     673            vector<string>::const_iterator givenSubs;
     674            toBeDeleted.clear();
     675            for (serverSubs=cSubs->second.begin(); serverSubs != cSubs->second.end(); serverSubs++)
     676            {
     677                for (givenSubs = cServicesList.begin(); givenSubs != cServicesList.end(); givenSubs++)
     678                    if (serverSubs->first == *givenSubs)
     679                        break;
     680                if (givenSubs == cServicesList.end())
     681                {
     682                    toBeDeleted.push_back(serverSubs->first);
     683                    serviceUpdated = true;
     684                }   
     685            }
     686            for (vector<string>::const_iterator it = toBeDeleted.begin(); it != toBeDeleted.end(); it++)
     687                cSubs->second.erase(*it);
     688            //now check for new services
     689            for (givenSubs = cServicesList.begin(); givenSubs != cServicesList.end(); givenSubs++)
     690            {
     691                if (*givenSubs == "SERVICE_LIST")
     692                    continue;
     693
     694                if (fHasWhiteList && (fWhiteList.find(*i + "/") == fWhiteList.end()) &&
    720695                                     (fWhiteList.find(*i + "/" + *givenSubs) == fWhiteList.end()) &&
    721696                                     (fWhiteList.find("/" + *givenSubs) == fWhiteList.end()))
    722                                     continue;
     697                    continue;
    723698                if (fHasBlackList && ((fBlackList.find(*i + "/") != fBlackList.end()) ||
    724699                                      (fBlackList.find(*i + "/" + *givenSubs) != fBlackList.end()) ||
     
    727702
    728703                if (cSubs->second.find(*givenSubs) == cSubs->second.end())
    729                                 {//service not found. Add it
    730                                         cSubs->second[*givenSubs].dimInfo = new DimStampedInfo(((*i) + "/" + *givenSubs).c_str(), const_cast<char*>(""), this);
    731                                         serviceUpdated = true;
    732                                         if(fDebugIsOn)
    733                                         {
    734                                                 stringstream str;
    735                                                 str << "Subscribing to service " << *i << "/" << *givenSubs;
    736                                                 Debug(str.str());       
    737                                         }
    738                                 }       
    739                         }
    740                 }
    741                 else //server not found in our list. Create its entry
    742                 {
    743                         fServiceSubscriptions[*i] = std::map<std::string, SubscriptionType>();
    744                         std::map<std::string, SubscriptionType>& liste = fServiceSubscriptions[*i];
    745                         for (std::vector<std::string>::const_iterator j = cServicesList.begin(); j!= cServicesList.end(); j++)
    746                         {
    747                                 if (*j == "SERVICE_LIST")
    748                                         continue;
     704                {//service not found. Add it
     705                    cSubs->second[*givenSubs].dimInfo = new DimStampedInfo(((*i) + "/" + *givenSubs).c_str(), const_cast<char*>(""), this);
     706                    serviceUpdated = true;
     707                    if(fDebugIsOn)
     708                    {
     709                        stringstream str;
     710                        str << "Subscribing to service " << *i << "/" << *givenSubs;
     711                        Debug(str.str());   
     712                    }
     713                }   
     714            }
     715        }
     716        else //server not found in our list. Create its entry
     717        {
     718            fServiceSubscriptions[*i] = map<string, SubscriptionType>();
     719            map<string, SubscriptionType>& liste = fServiceSubscriptions[*i];
     720            for (vector<string>::const_iterator j = cServicesList.begin(); j!= cServicesList.end(); j++)
     721            {
     722                if (*j == "SERVICE_LIST")
     723                    continue;
    749724                if (fHasWhiteList && (fWhiteList.find(*i + "/") == fWhiteList.end()) &&
    750725                                     (fWhiteList.find(*i + "/" + *j) == fWhiteList.end()) &&
     
    756731                    continue;
    757732
    758                                        
    759                                 liste[*j].dimInfo = new DimStampedInfo(((*i) + "/" + (*j)).c_str(), const_cast<char*>(""), this);
    760                                 serviceUpdated = true;
    761                                 if(fDebugIsOn)
    762                                 {
    763                                         stringstream str;
    764                                         str << "Subscribing to service " << *i << "/" << *j;
    765                                         Debug(str.str());       
    766                                 }
    767                         }
    768                 }       
    769         }
    770         return serviceUpdated;
     733                liste[*j].dimInfo = new DimStampedInfo(((*i) + "/" + (*j)).c_str(), const_cast<char*>(""), this);
     734                serviceUpdated = true;
     735                if(fDebugIsOn)
     736                {
     737                    stringstream str;
     738                    str << "Subscribing to service " << *i << "/" << *j;
     739                    Debug(str.str());   
     740                }
     741            }
     742        }   
     743    }
     744    return serviceUpdated;
    771745}
    772746// --------------------------------------------------------------------------
     
    776750DataLogger::~DataLogger()
    777751{
    778         if (fDebugIsOn)
    779         {
    780                 Debug("DataLogger destruction starts");
    781         }
    782         fDestructing = true;
    783         //first let's go to the ready state
    784         //TODO some closing done below has already been executed by GoToReady. figure out what should be removed.
    785         GoToReadyPlease();
    786         //release the services subscriptions
    787         fServiceSubscriptions.clear();
    788         //exit the monitoring loop
    789         fContinueMonitoring = false;
    790 //      delete[] fDimBuffer;
    791         fMonitoringThread.join();
    792         //close the files
    793         if (fNightlyLogFile.is_open())
    794                 fNightlyLogFile.close();
    795         if (fNightlyReportFile.is_open())
    796                 fNightlyReportFile.close();
    797         if (fRunLogFile.is_open())
    798                 fRunLogFile.close();
    799         if (fRunReportFile.is_open())
    800                 fRunReportFile.close();
    801         delete fOpenedNightlyFiles;
    802         delete fOpenedRunFiles;
    803         delete fNumSubAndFits;
    804 //TODO notify that all files were closed
     752    if (fDebugIsOn)
     753    {
     754        Debug("DataLogger destruction starts");   
     755    }
     756    fDestructing = true;
     757    //first let's go to the ready state
     758    GoToReadyPlease();
     759    //release the services subscriptions
     760    fServiceSubscriptions.clear();
     761    //exit the monitoring loop
     762    fContinueMonitoring = false;
     763
     764    fMonitoringThread.join();
     765    //close the files
     766    if (fNightlyLogFile.is_open())
     767        fNightlyLogFile.close();
     768    if (fNightlyReportFile.is_open())
     769        fNightlyReportFile.close();
     770    if (fRunLogFile.is_open())
     771        fRunLogFile.close();
     772    if (fRunReportFile.is_open())
     773        fRunReportFile.close();
     774    delete fOpenedNightlyFiles;
     775    delete fOpenedRunFiles;
     776    delete fNumSubAndFits;
    805777#ifdef HAVE_FITS
    806 #ifdef ONE_RUN_FITS_ONLY
    807         if (fRunFitsFile != NULL)
    808                 delete fRunFitsFile;
    809         fRunFitsFile = NULL;
     778    if (fRunFitsFile != NULL)
     779        delete fRunFitsFile;
     780    fRunFitsFile = NULL;
    810781#endif
    811 #endif
    812         if (fDebugIsOn)
    813         {
    814                 Debug("DataLogger desctruction ends"); 
    815         }
     782    if (fDebugIsOn)
     783    {
     784        Debug("DataLogger desctruction ends");   
     785    }
    816786}
    817787
     
    823793{
    824794    // Make sure getTimestamp is called _before_ getTimestampMillisecs
    825         if (fDestructing)
    826                 return;
     795    if (fDestructing)
     796        return;
    827797
    828798    DimInfo* I = getInfo();
    829         SubscriptionsListType::iterator x;
    830         std::map<std::string, SubscriptionType>::iterator y;
    831         if (I==NULL)
    832         {
    833                 if (CheckForServicesUpdate())
    834                 {
    835                         //services were updated. Notify
    836                         fNumSubAndFitsData.numSubscriptions = 0;
    837                         for (x=fServiceSubscriptions.begin(); x != fServiceSubscriptions.end(); x++)
    838                                 fNumSubAndFitsData.numSubscriptions += x->second.size();
    839                         if (fNumSubAndFitsIsOn)
    840                         {
    841                                 if (fDebugIsOn)
    842                                 {
    843                                         stringstream str;
    844                                         str << "Updating number of subscriptions service: Num Subs=" << fNumSubAndFitsData.numSubscriptions << " Num open FITS=" << fNumSubAndFitsData.numOpenFits;
    845                                         Debug(str.str());       
    846                                 }
    847                                 fNumSubAndFits->updateService();
    848                         }
    849                 }
    850                 return;
    851         }
    852         //check if the service pointer corresponds to something that we subscribed to
    853         //this is a fix for a bug that provides bad Infos when a server starts
    854         bool found = false;
    855         for (x=fServiceSubscriptions.begin(); x != fServiceSubscriptions.end(); x++)
    856         {//find current service is subscriptions
    857                 for (y=x->second.begin(); y!=x->second.end();y++)
    858                         if (y->second.dimInfo == I)
    859                         {
    860                                 found = true;   
    861                                 break;
    862                         }
    863                 if (found)
    864                         break;
    865         }
    866         if (!found)
    867                 return;
    868         if (I->getSize() <= 0)
    869                 return;
     799    SubscriptionsListType::iterator x;
     800    map<string, SubscriptionType>::iterator y;
     801    if (I==NULL)
     802    {
     803        if (CheckForServicesUpdate())
     804        {
     805            //services were updated. Notify
     806            fNumSubAndFitsData.numSubscriptions = 0;
     807            for (x=fServiceSubscriptions.begin(); x != fServiceSubscriptions.end(); x++)
     808                fNumSubAndFitsData.numSubscriptions += x->second.size();
     809            if (fNumSubAndFitsIsOn)
     810            {
     811                if (fDebugIsOn)
     812                {
     813                    stringstream str;
     814                    str << "Updating number of subscriptions service: Num Subs=" << fNumSubAndFitsData.numSubscriptions << " Num open FITS=" << fNumSubAndFitsData.numOpenFits;
     815                    Debug(str.str());   
     816                }
     817                fNumSubAndFits->updateService();
     818            }
     819        }
     820        return;
     821    }
     822    //check if the service pointer corresponds to something that we subscribed to
     823    //this is a fix for a bug that provides bad Infos when a server starts
     824    bool found = false;
     825    for (x=fServiceSubscriptions.begin(); x != fServiceSubscriptions.end(); x++)
     826    {//find current service is subscriptions
     827        for (y=x->second.begin(); y!=x->second.end();y++)
     828            if (y->second.dimInfo == I)
     829            {
     830                found = true;   
     831                break;
     832            }
     833        if (found)
     834            break;
     835    }
     836    if (!found)
     837        return;
     838    if (I->getSize() <= 0)
     839        return;
    870840
    871841        // Make sure that getTimestampMillisecs is NEVER called before
    872842        // getTimestamp is properly called
    873843        // check that the message has been updated by something, i.e. must be different from its initial value
    874         if (I->getTimestamp() == 0)
    875                 return;
    876 
    877         CheckForRunNumber(I);
    878 
    879         if (fPreviousRunNumber != fRunNumber)
    880         {//run number has changed. close and reopen run files.
    881                 StopRunPlease();
    882                 StartRunPlease();
    883                 fPreviousRunNumber = fRunNumber;
    884         }
    885 
    886         ReportPlease(I, y->second);
     844    if (I->getTimestamp() == 0)
     845        return;
     846
     847    CheckForRunNumber(I);
     848
     849    if (fPreviousRunNumber != fRunNumber)
     850    {//run number has changed. close and reopen run files.
     851        StopRunPlease();
     852        StartRunPlease();
     853        fPreviousRunNumber = fRunNumber;
     854    }
     855
     856    ReportPlease(I, y->second);
    887857
    888858}
     
    893863//! If so, then remember it. A run number is required to open the run-log file
    894864//! @param I
    895 //!             the current DimInfo
     865//!        the current DimInfo
    896866//
    897867void DataLogger::CheckForRunNumber(DimInfo* I)
    898868{
    899         if (strstr(I->getName(), fRunNumberInfo) != NULL)
    900         {//assumes that the run number is an integer
    901                 //TODO check the format here
    902                 fRunNumber = I->getInt();       
    903                 stringstream str;
    904                 str << "New run number is " << fRunNumber;
    905                 Message(str.str());
    906         }
     869    if (strstr(I->getName(), fRunNumberInfo) != NULL)
     870    {//assumes that the run number is an integer
     871        fRunNumber = I->getInt();   
     872        stringstream str;
     873        str << "New run number is " << fRunNumber;
     874        Message(str.str());
     875    }
    907876}
    908877
     
    911880//! write infos to log files.
    912881//! @param I
    913 //!     The current DimInfo
     882//!     The current DimInfo
    914883//! @param sub
    915 //!             The dataLogger's subscription corresponding to this DimInfo
     884//!        The dataLogger's subscription corresponding to this DimInfo
    916885//
    917886void DataLogger::ReportPlease(DimInfo* I, SubscriptionType& sub)
    918887{
    919         //should we log or report this info ? (i.e. is it a message ?)
    920         bool isItaReport = ((strstr(I->getName(), "Message") == NULL) && (strstr(I->getName(), "MESSAGE") == NULL));
    921         if (I->getFormat()[0] == 'C')
    922                 isItaReport = false;
    923         //TODO add service exclusion
    924        
    925         if (!fNightlyReportFile.is_open())
    926                 return;
    927 
    928         //create the converter for that service
    929         if (sub.fConv == NULL && isItaReport)
    930         {
    931                 //trick the converter in case of 'C'. why do I do this ? well simple: the converter checks that the right number
    932                 //of bytes was written. because I skip 'C' with fits, the bytes will not be allocated, hence the "size copied ckeck"
    933                 //of the converter will fail, hence throwing an exception.
    934                 std::string fakeFormat(I->getFormat());
    935                 if (fakeFormat[fakeFormat.size()-1] == 'C')
    936                         fakeFormat = fakeFormat.substr(0, fakeFormat.size()-1);
    937                 sub.fConv = new Converter(Out(), I->getFormat());       
    938                 if (!sub.fConv)
    939                 {
    940                         std::stringstream str;
    941                         str << "Couldn't properly parse the format... service " << sub.dimInfo->getName() << " ignored.";
    942                         Error(str);
    943                         return;
    944                 }
    945         }
    946                
    947         //construct the header
    948         std::stringstream header;
    949         Time cTime(I->getTimestamp(), I->getTimestampMillisecs()*1000);
    950         fQuality = I->getQuality();
    951         fMjD = cTime.Mjd();
    952 
    953         if (isItaReport)
    954         {
    955                 //write text header
    956                 header << I->getName() << " " << fQuality << " ";
    957                 header << cTime.Y() << " " << cTime.M() << " " << cTime.D() << " ";
    958                 header << cTime.h() << " " << cTime.m() << " " << cTime.s() << " ";
    959                 header << cTime.ms() << " " << I->getTimestamp() << " ";
    960 
    961                 std::string text;
     888    //should we log or report this info ? (i.e. is it a message ?)
     889    bool isItaReport = ((strstr(I->getName(), "Message") == NULL) && (strstr(I->getName(), "MESSAGE") == NULL));
     890    if (I->getFormat()[0] == 'C')
     891        isItaReport = false;
     892   
     893    if (!fNightlyReportFile.is_open())
     894        return;
     895
     896    //create the converter for that service
     897    if (sub.fConv == NULL && isItaReport)
     898    {
     899        //trick the converter in case of 'C'. why do I do this ? well simple: the converter checks that the right number
     900        //of bytes was written. because I skip 'C' with fits, the bytes will not be allocated, hence the "size copied ckeck"
     901        //of the converter will fail, hence throwing an exception.
     902        string fakeFormat(I->getFormat());
     903        if (fakeFormat[fakeFormat.size()-1] == 'C')
     904            fakeFormat = fakeFormat.substr(0, fakeFormat.size()-1);
     905        sub.fConv = new Converter(Out(), I->getFormat());   
     906        if (!sub.fConv)
     907        {
     908            stringstream str;
     909            str << "Couldn't properly parse the format... service " << sub.dimInfo->getName() << " ignored.";
     910            Error(str);
     911            return;   
     912        }
     913    }
     914       
     915    //construct the header
     916    stringstream header;
     917    Time cTime(I->getTimestamp(), I->getTimestampMillisecs()*1000);
     918    fQuality = I->getQuality();
     919    fMjD = cTime.Mjd();
     920
     921    if (isItaReport)
     922    {
     923        //write text header
     924        header << I->getName() << " " << fQuality << " ";
     925        header << cTime.Y() << " " << cTime.M() << " " << cTime.D() << " ";
     926        header << cTime.h() << " " << cTime.m() << " " << cTime.s() << " ";
     927        header << cTime.ms() << " " << I->getTimestamp() << " ";
     928
     929        string text;
    962930        try
    963931        {
    964                 text = sub.fConv->GetString(I->getData(), I->getSize());
    965         }
    966         catch (const std::runtime_error &e)
    967         {
    968                 Out() << kRed << e.what() << endl;
    969                 std::stringstream str;
    970                 str << "Could not properly parse the data for service " << sub.dimInfo->getName();
    971                 str << " reason: " << e.what() << ". Entry ignored";
     932            text = sub.fConv->GetString(I->getData(), I->getSize());
     933        }
     934        catch (const runtime_error &e)
     935        {
     936            Out() << kRed << e.what() << endl;
     937            stringstream str;
     938            str << "Could not properly parse the data for service " << sub.dimInfo->getName();
     939            str << " reason: " << e.what() << ". Entry ignored";
    972940            Error(str);
    973941            return;
    974942        }
    975943
    976                 if (text.empty())
    977                 {
    978                         std::stringstream str;
    979                         str << "Service " << sub.dimInfo->getName() << " sent an empty string";
    980                         Info(str);
    981                 return;
    982                 }
     944        if (text.empty())
     945        {
     946            stringstream str;
     947            str << "Service " << sub.dimInfo->getName() << " sent an empty string";
     948            Info(str);
     949            return;
     950        }
    983951        //replace bizarre characters by white space
    984952        replace(text.begin(), text.end(), '\n', '\\');
    985         replace_if(text.begin(), text.end(), std::ptr_fun<int, int>(&std::iscntrl), ' ');
     953        replace_if(text.begin(), text.end(), ptr_fun<int, int>(&iscntrl), ' ');
    986954       
    987955        //write entry to Nightly report
    988                 if (fNightlyReportFile.is_open())
    989                 {
    990                         if (fDebugIsOn)
    991                         {
    992                                 stringstream str;
    993                                 str << "Writing: \"" << header.str() << text << "\" to Nightly report file";
    994                                 Debug(str.str());       
    995                         }
    996                         fNightlyReportFile << header.str() << text << std::endl;
    997                         //check if either eof, bailbit or batbit are set
    998                         if (!fNightlyReportFile.good())
    999                         {
    1000                                 Error("An error occured while writing to the nightly report file. Closing it");
    1001                                 if (fNightlyReportFile.is_open())
    1002                                         fNightlyReportFile.close();
    1003                         }
    1004                 }
    1005                 //write entry to run-report
    1006                 if (fRunReportFile.is_open())
    1007                 {
    1008                         if (fDebugIsOn)
    1009                         {
    1010                                 stringstream str;
    1011                                 str << "Writing: \"" << header.str() << text << "\" to Run report file";
    1012                                 Debug(str.str());       
    1013                         }
    1014                         fRunReportFile << header.str() << text << std::endl;
    1015                         if (!fRunReportFile.good())
    1016                         {
    1017                                 Error("An error occured while writing to the run report file. Closing it.");
    1018                                 if (fRunReportFile.is_open())
    1019                                         fRunReportFile.close();
    1020                         }
    1021                 }
    1022         }
    1023         else
    1024         {//write entry to both Nightly and run logs
    1025                 std::string n = I->getName();
    1026                 std::stringstream msg;
    1027                 msg << n << ": " << I->getString();//n.substr(0, n.find_first_of('/')) << ": " << I->getString();
    1028 
    1029                 if (fNightlyLogFile.is_open())
    1030                 {
    1031                         if (fDebugIsOn)
    1032                         {
    1033                                 stringstream str;
    1034                                 str << "Writing: \"" << msg.str() << "\" to Nightly log file";
    1035                                 Debug(str.str());       
    1036                         }
    1037                         MessageImp nightlyMess(fNightlyLogFile);
    1038                         nightlyMess.Write(cTime, msg.str().c_str(), fQuality);
    1039                         if (!fNightlyLogFile.good())
    1040                         {
    1041                                 Error("An error occured while writing to the nightly log file. Closing it.");
    1042                                 if (fNightlyLogFile.is_open())
    1043                                         fNightlyLogFile.close();       
    1044                         }
    1045                 }
    1046                 if (fRunLogFile.is_open())
    1047                 {
    1048                         if (fDebugIsOn)
    1049                         {
    1050                                 stringstream str;
    1051                                 str << "Writing: \"" << msg.str() << "\" to Run log file";
    1052                                 Debug(str.str());       
    1053                         }
    1054                         MessageImp runMess(fRunLogFile);
    1055                         runMess.Write(cTime, msg.str().c_str(), fQuality);
    1056                         if (!fRunLogFile.good())
    1057                         {
    1058                                 Error("An error occured while writing to the run log file. Closing it.");
    1059                                 if (fRunLogFile.is_open())
    1060                                         fRunLogFile.close();   
    1061                         }
    1062                 }
    1063         }
     956        if (fNightlyReportFile.is_open())
     957        {
     958            if (fDebugIsOn)
     959            {
     960                stringstream str;
     961                str << "Writing: \"" << header.str() << text << "\" to Nightly report file";
     962                Debug(str.str());   
     963            }
     964            fNightlyReportFile << header.str() << text << endl;
     965            //check if either eof, bailbit or batbit are set
     966            if (!fNightlyReportFile.good())
     967            {
     968                Error("An error occured while writing to the nightly report file. Closing it");
     969                if (fNightlyReportFile.is_open())
     970                    fNightlyReportFile.close();
     971            }
     972        }
     973        //write entry to run-report
     974        if (fRunReportFile.is_open())
     975        {
     976            if (fDebugIsOn)
     977            {
     978                stringstream str;
     979                str << "Writing: \"" << header.str() << text << "\" to Run report file";
     980                Debug(str.str());   
     981            }
     982            fRunReportFile << header.str() << text << endl;
     983            if (!fRunReportFile.good())
     984            {
     985                Error("An error occured while writing to the run report file. Closing it.");
     986                if (fRunReportFile.is_open())
     987                    fRunReportFile.close();   
     988            }
     989        }
     990    }
     991    else
     992    {//write entry to both Nightly and run logs
     993        string n = I->getName();
     994        stringstream msg;
     995        msg << n << ": " << I->getString();//n.substr(0, n.find_first_of('/')) << ": " << I->getString();
     996
     997        if (fNightlyLogFile.is_open())
     998        {
     999            if (fDebugIsOn)
     1000            {
     1001                stringstream str;
     1002                str << "Writing: \"" << msg.str() << "\" to Nightly log file";
     1003                Debug(str.str());   
     1004            }
     1005            MessageImp nightlyMess(fNightlyLogFile);
     1006            nightlyMess.Write(cTime, msg.str().c_str(), fQuality);
     1007            if (!fNightlyLogFile.good())
     1008            {
     1009                Error("An error occured while writing to the nightly log file. Closing it.");
     1010                if (fNightlyLogFile.is_open())
     1011                    fNightlyLogFile.close();   
     1012            }
     1013        }
     1014        if (fRunLogFile.is_open())
     1015        {
     1016            if (fDebugIsOn)
     1017            {
     1018                stringstream str;
     1019                str << "Writing: \"" << msg.str() << "\" to Run log file";
     1020                Debug(str.str());   
     1021            }
     1022            MessageImp runMess(fRunLogFile);
     1023            runMess.Write(cTime, msg.str().c_str(), fQuality);
     1024            if (!fRunLogFile.good())
     1025            {
     1026                Error("An error occured while writing to the run log file. Closing it.");
     1027                if (fRunLogFile.is_open())
     1028                    fRunLogFile.close();   
     1029            }
     1030        }
     1031    }
    10641032
    10651033#ifdef HAVE_FITS
    1066         if (isItaReport)
    1067         {
    1068                 if (!sub.nightlyFile.IsOpen() || !sub.runFile.IsOpen())
    1069                         OpenFITSFilesPlease(sub);       
    1070                 WriteToFITS(sub);
    1071         }       
     1034    if (isItaReport)
     1035    {
     1036        if (!sub.nightlyFile.IsOpen() || !sub.runFile.IsOpen())
     1037            OpenFITSFilesPlease(sub);   
     1038        WriteToFITS(sub);
     1039    }   
    10721040#endif
    10731041
     
    10781046//! write messages to logs.
    10791047//! @param evt
    1080 //!             the current event to log
     1048//!        the current event to log
    10811049//! @returns
    1082 //!             the new state. Currently, always the current state
     1050//!        the new state. Currently, always the current state
    10831051//!
    10841052//! @deprecated
    10851053//!    I guess that this function should not be any longer
    10861054//
    1087 //TODO isn't that function not used any longer ? If so I guess that we should get rid of it...
    10881055//Otherwise re-write it properly with the MessageImp class
    10891056int DataLogger::LogMessagePlease(const Event& evt)
    10901057{
    1091         if (!fNightlyLogFile.is_open())
    1092                 return GetCurrentState();
    1093        
    1094         std::stringstream header;
    1095         const Time& cTime = evt.GetTime();
    1096         header << evt.GetName() << " " << cTime.Y() << " " << cTime.M() << " " << cTime.D() << " ";
    1097         header << cTime.h() << " " << cTime.m() << " " << cTime.s() << " ";
    1098         header << cTime.ms() << " ";
    1099                
     1058    if (!fNightlyLogFile.is_open())
     1059        return GetCurrentState();
     1060    Warn("LogMessagePlease has not been checked nor updated since a long while. Undefined behavior to be expected");
     1061    stringstream header;
     1062    const Time& cTime = evt.GetTime();
     1063    header << evt.GetName() << " " << cTime.Y() << " " << cTime.M() << " " << cTime.D() << " ";
     1064    header << cTime.h() << " " << cTime.m() << " " << cTime.s() << " ";
     1065    header << cTime.ms() << " ";
     1066       
    11001067    const Converter conv(Out(), evt.GetFormat());
    11011068    if (!conv)
    11021069    {
    1103         Error("Couldn't properly parse the format... ignored.");
     1070        Error("Couldn't properly parse the format... ignored.");
    11041071        return GetCurrentState();
    11051072    }
    11061073
    1107     std::string text;
     1074    string text;
    11081075    try
    11091076    {
    1110         text = conv.GetString(evt.GetData(), evt.GetSize());
    1111     }
    1112     catch (const std::runtime_error &e)
    1113     {
    1114         Out() << kRed << e.what() << endl;
     1077        text = conv.GetString(evt.GetData(), evt.GetSize());
     1078    }
     1079    catch (const runtime_error &e)
     1080    {
     1081        Out() << kRed << e.what() << endl;
    11151082        Error("Couldn't properly parse the data... ignored.");
    11161083        return GetCurrentState();
    11171084    }
    11181085
    1119         if (text.empty())
     1086    if (text.empty())
    11201087        return GetCurrentState();
    11211088
    11221089    //replace bizarre characters by white space
    11231090    replace(text.begin(), text.end(), '\n', '\\');
    1124     replace_if(text.begin(), text.end(), std::ptr_fun<int, int>(&std::iscntrl), ' ');
    1125         if (fDebugIsOn)
    1126         {
    1127                 stringstream str;
    1128                 str << "Logging: \"" << header << text << "\"";
    1129                 Debug(str.str());       
    1130         }
    1131        
    1132         if (fNightlyLogFile.is_open())
    1133         {
    1134                 fNightlyLogFile << header;
    1135                 if (!fNightlyLogFile.good())
    1136                 {
    1137                         Error("An error occured while writing to the run log file. Closing it.");
    1138                         if (fNightlyLogFile.is_open())
    1139                                 fNightlyLogFile.close();       
    1140                 }
    1141         }
    1142         if (fRunLogFile.is_open())
    1143         {
    1144                 fRunLogFile << header;
    1145                 if (!fRunLogFile.good())
    1146                 {
    1147                         Error("An error occured while writing to the run log file. Closing it.");
    1148                         if (fRunLogFile.is_open())
    1149                                 fRunLogFile.close();   
    1150                 }
    1151         }
    1152         if (fNightlyLogFile.is_open())
    1153         {
    1154                 fNightlyLogFile << text;
    1155                 if (!fNightlyLogFile.good())
    1156                 {
    1157                         Error("An error occured while writing to the run log file. Closing it.");
    1158                         if (fNightlyLogFile.is_open())
    1159                                 fNightlyLogFile.close();       
    1160                 }
    1161         }
    1162         if (fRunLogFile.is_open())
    1163         {
    1164                 fRunLogFile << text;
    1165                 if (!fRunLogFile.good())
    1166                 {
    1167                         Error("An error occured while writing to the run log file. Closing it.");
    1168                         if (fRunLogFile.is_open())
    1169                                 fRunLogFile.close();   
    1170                 }
    1171         }
    1172         return GetCurrentState();
     1091    replace_if(text.begin(), text.end(), ptr_fun<int, int>(&iscntrl), ' ');
     1092    if (fDebugIsOn)
     1093    {
     1094        stringstream str;
     1095        str << "Logging: \"" << header << text << "\"";
     1096        Debug(str.str());   
     1097    }
     1098   
     1099    if (fNightlyLogFile.is_open())
     1100    {
     1101        fNightlyLogFile << header;
     1102        if (!fNightlyLogFile.good())
     1103        {
     1104            Error("An error occured while writing to the run log file. Closing it.");
     1105            if (fNightlyLogFile.is_open())
     1106                fNightlyLogFile.close();   
     1107        }
     1108    }
     1109    if (fRunLogFile.is_open())
     1110    {
     1111        fRunLogFile << header;
     1112        if (!fRunLogFile.good())
     1113        {
     1114            Error("An error occured while writing to the run log file. Closing it.");
     1115            if (fRunLogFile.is_open())
     1116                fRunLogFile.close();   
     1117        }
     1118    }
     1119    if (fNightlyLogFile.is_open())
     1120    {
     1121        fNightlyLogFile << text;
     1122        if (!fNightlyLogFile.good())
     1123        {
     1124            Error("An error occured while writing to the run log file. Closing it.");
     1125            if (fNightlyLogFile.is_open())
     1126                fNightlyLogFile.close();   
     1127        }
     1128    }
     1129    if (fRunLogFile.is_open())
     1130    {
     1131        fRunLogFile << text;
     1132        if (!fRunLogFile.good())
     1133        {
     1134            Error("An error occured while writing to the run log file. Closing it.");
     1135            if (fRunLogFile.is_open())
     1136                fRunLogFile.close();   
     1137        }
     1138    }
     1139    return GetCurrentState();
    11731140}
    11741141// --------------------------------------------------------------------------
     
    11761143//! print the dataLogger's current state. invoked by the PRINT command
    11771144//! @param evt
    1178 //!             the current event. Not used by the method
     1145//!        the current event. Not used by the method
    11791146//! @returns
    1180 //!             the new state. Which, in that case, is the current state
     1147//!        the new state. Which, in that case, is the current state
    11811148//!
    11821149int DataLogger::PrintStatePlease(const Event& )
    11831150{
    1184         Message("-----------------------------------------");
    1185         Message("------ DATA LOGGER CURRENT STATE --------");
    1186         Message("-----------------------------------------");
    1187         //print the path configuration
    1188         std::string actualTargetDir;
    1189         if (fNightlyFileName == ".")
    1190         {
    1191             char currentPath[FILENAME_MAX];
    1192             if (getcwd(currentPath, sizeof(currentPath)))
    1193                 actualTargetDir = currentPath;
    1194         }
    1195         else
    1196                 actualTargetDir = fNightlyFileName;
    1197         Message("Nightly Path: " + actualTargetDir);
    1198         if (fRunFileName == ".")
    1199         {
    1200             char currentPath[FILENAME_MAX];
    1201             if (getcwd(currentPath, sizeof(currentPath)))
    1202                 actualTargetDir = currentPath;
    1203         }
    1204         else
    1205                 actualTargetDir = fRunFileName;
    1206         Message("Run Path: " + actualTargetDir);
    1207         stringstream str;
    1208         str << "Run Number: " << fRunNumber;
    1209         Message(str.str());
    1210         Message("----------- OPENED FILES ----------------");
    1211         //print all the open files.
    1212         if (fNightlyLogFile.is_open())
    1213                 Message("Nightly Log..........OPEN");
    1214         else
    1215                 Message("Nightly log........CLOSED");
    1216         if (fNightlyReportFile.is_open())
    1217                 Message("Nightly Report.......OPEN");
    1218         else
    1219                 Message("Nightly Report.....CLOSED");
    1220         if (fRunLogFile.is_open())
    1221                 Message("Run Log..............OPEN");
    1222         else
    1223                 Message("Run Log............CLOSED");
    1224         if (fRunReportFile.is_open())
    1225                 Message("Run Report...........OPEN");
    1226         else
    1227                 Message("Run Report.........CLOSED");
    1228         bool statWarning = false;
    1229         DataLoggerStats statVar;
    1230         calculateTotalSizeWritten(statVar, statWarning, false);
    1231         Message("---------------- STATS ------------------");
    1232         str.str("");
    1233         str << "Total Size written: " << statVar.sizeWritten << " bytes.";
     1151    Message("-----------------------------------------");
     1152    Message("------ DATA LOGGER CURRENT STATE --------");
     1153    Message("-----------------------------------------");
     1154    //print the path configuration
     1155    string actualTargetDir;
     1156    if (fNightlyFileName == ".")
     1157    {
     1158        char currentPath[FILENAME_MAX];
     1159        if (getcwd(currentPath, sizeof(currentPath)))
     1160            actualTargetDir = currentPath;
     1161    }
     1162    else
     1163        actualTargetDir = fNightlyFileName;
     1164    Message("Nightly Path: " + actualTargetDir);
     1165    if (fRunFileName == ".")
     1166    {
     1167        char currentPath[FILENAME_MAX];
     1168        if (getcwd(currentPath, sizeof(currentPath)))
     1169            actualTargetDir = currentPath;
     1170    }
     1171    else
     1172        actualTargetDir = fRunFileName;
     1173    Message("Run Path: " + actualTargetDir);
     1174    stringstream str;
     1175    str << "Run Number: " << fRunNumber;
     1176    Message(str.str());
     1177    Message("----------- OPENED FILES ----------------");
     1178    //print all the open files.
     1179    if (fNightlyLogFile.is_open())
     1180        Message("Nightly Log..........OPEN");
     1181    else
     1182        Message("Nightly log........CLOSED");
     1183    if (fNightlyReportFile.is_open())
     1184        Message("Nightly Report.......OPEN");
     1185    else
     1186        Message("Nightly Report.....CLOSED");
     1187    if (fRunLogFile.is_open())
     1188        Message("Run Log..............OPEN");
     1189    else
     1190        Message("Run Log............CLOSED");
     1191    if (fRunReportFile.is_open())
     1192        Message("Run Report...........OPEN");
     1193    else
     1194        Message("Run Report.........CLOSED");
     1195    bool statWarning = false;
     1196    DataLoggerStats statVar;
     1197    calculateTotalSizeWritten(statVar, statWarning, false);
     1198    Message("---------------- STATS ------------------");
     1199    str.str("");
     1200    str << "Total Size written: " << statVar.sizeWritten << " bytes.";
    12341201        Message(str.str());
    1235         str.str("");
    1236         str << "Disk free space:    " << statVar.freeSpace   << " bytes.";
     1202    str.str("");
     1203    str << "Disk free space:    " << statVar.freeSpace   << " bytes.";
    12371204        Message(str.str());
    12381205    str.str("");
    12391206    str << "Statistics are updated every " << fStatsPeriodDuration << " seconds";
    12401207    if (fStatsPeriodDuration != 0)
    1241         Message(str);
     1208        Message(str);
    12421209    else
    1243         Message("Statistics updates are currently disabled");
    1244         Message("----------- DIM SUBSCRIPTIONS -----------");
    1245 
    1246         str.str("");
    1247         str << "There are " << fNumSubAndFitsData.numSubscriptions << " active DIM subscriptions:";
    1248         Message(str.str());
    1249 
    1250         for (std::map<const std::string, std::map<std::string, SubscriptionType>>::const_iterator it=fServiceSubscriptions.begin(); it!= fServiceSubscriptions.end();it++)
    1251         {
    1252                 Message("Server "+it->first);
    1253                 for (std::map<std::string, SubscriptionType>::const_iterator it2=it->second.begin(); it2!=it->second.end(); it2++)
    1254                         Message(" -> "+it2->first);
    1255         }
    1256         if (fHasBlackList)
    1257         {
    1258             Message("------------- BLOCK LIST ----------------");
    1259             for (set<string>::iterator it=fBlackList.begin(); it != fBlackList.end(); it++)
    1260                 Message(*it);
    1261         }
    1262         if (fHasWhiteList)
    1263         {
    1264                         Message("----------- ALLOW LIST ------------------");
    1265                         for (set<string>::iterator it=fWhiteList.begin(); it != fWhiteList.end(); it++)
    1266                             Message(*it);
    1267         }
    1268 
    1269         return GetCurrentState();
     1210        Message("Statistics updates are currently disabled");
     1211    Message("----------- DIM SUBSCRIPTIONS -----------");
     1212
     1213    str.str("");
     1214    str << "There are " << fNumSubAndFitsData.numSubscriptions << " active DIM subscriptions:";
     1215    Message(str.str());
     1216
     1217    for (map<const string, map<string, SubscriptionType> >::const_iterator it=fServiceSubscriptions.begin(); it!= fServiceSubscriptions.end();it++)
     1218    {
     1219        Message("Server "+it->first);
     1220        for (map<string, SubscriptionType>::const_iterator it2=it->second.begin(); it2!=it->second.end(); it2++)
     1221            Message(" -> "+it2->first);
     1222    }
     1223    if (fHasBlackList)
     1224    {
     1225        Message("------------- BLOCK LIST ----------------");
     1226        for (set<string>::iterator it=fBlackList.begin(); it != fBlackList.end(); it++)
     1227            Message(*it);
     1228    }
     1229    if (fHasWhiteList)
     1230    {
     1231            Message("----------- ALLOW LIST ------------------");
     1232            for (set<string>::iterator it=fWhiteList.begin(); it != fWhiteList.end(); it++)
     1233                Message(*it);
     1234    }
     1235    if (fGrouping.size() != 0)
     1236    {
     1237            Message("--------- GROUPING LIST -----------------");
     1238            Message("The following servers and/or services will be grouping under a single run fits file:");
     1239            for (set<string>::iterator it=fGrouping.begin(); it != fGrouping.end(); it++)
     1240                Message(*it);
     1241    }
     1242    Message("-----------------------------------------");
     1243    Message("------ END OF DATA LOGGER STATE ---------");
     1244    Message("-----------------------------------------");
     1245
     1246    return GetCurrentState();
    12701247}
    12711248
     
    12741251//! turn debug mode on and off
    12751252//! @param evt
    1276 //!             the current event. contains the instruction string: On, Off, on, off, ON, OFF, 0 or 1
     1253//!        the current event. contains the instruction string: On, Off, on, off, ON, OFF, 0 or 1
    12771254//! @returns
    1278 //!             the new state. Which, in that case, is the current state
     1255//!        the new state. Which, in that case, is the current state
    12791256//!
    12801257int DataLogger::SetDebugOnOff(const Event& evt)
    12811258{
    1282         bool backupDebug = fDebugIsOn;
    1283         fDebugIsOn = evt.GetBool();
    1284         if (fDebugIsOn == backupDebug)
    1285                 Warn("Warning: debug mode was already in the requested state");
    1286         else
    1287         {
    1288                 stringstream str;
    1289                 str << "Debug mode is now " << fDebugIsOn;
    1290                 Message(str.str());
    1291         }
    1292         return GetCurrentState();
     1259    bool backupDebug = fDebugIsOn;
     1260    fDebugIsOn = evt.GetBool();
     1261    if (fDebugIsOn == backupDebug)
     1262        Warn("Warning: debug mode was already in the requested state");
     1263    else
     1264    {
     1265        stringstream str;
     1266        str << "Debug mode is now " << fDebugIsOn;
     1267        Message(str.str());
     1268    }
     1269    return GetCurrentState();
    12931270}
    12941271// --------------------------------------------------------------------------
     
    12961273//! set the statistics update period duration. 0 disables the statistics
    12971274//! @param evt
    1298 //!             the current event. contains the new duration.
     1275//!        the current event. contains the new duration.
    12991276//! @returns
    1300 //!             the new state. Which, in that case, is the current state
     1277//!        the new state. Which, in that case, is the current state
    13011278//!
    13021279int DataLogger::SetStatsPeriod(const Event& evt)
    13031280{
    1304         float backupDuration = fStatsPeriodDuration;
    1305         fStatsPeriodDuration = evt.GetFloat();
    1306         if (fStatsPeriodDuration < 0)
    1307         {
    1308                 Error("Statistics period duration should be greater than zero. Discarding provided value.");
    1309                 fStatsPeriodDuration = backupDuration;
    1310                 return GetCurrentState();       
    1311         }
    1312         if (fStatsPeriodDuration != fStatsPeriodDuration)
    1313         {
    1314                 Error("Provided duration does not appear to be a valid float. discarding it.");
    1315                 fStatsPeriodDuration = backupDuration;
    1316                 return GetCurrentState();       
    1317         }
    1318         if (backupDuration == fStatsPeriodDuration)
    1319                 Warn("Warning: statistics period was not modified: supplied value already in use");
    1320         else
    1321         {
    1322                 if (fStatsPeriodDuration == 0.0f)
    1323                         Message("Statistics are now OFF");
    1324                 else
    1325                 {
    1326                         stringstream str;
    1327                         str << "Statistics period is now " << fStatsPeriodDuration << " seconds";
    1328                         Message(str.str());     
    1329                 }       
    1330         }
    1331         return GetCurrentState();
     1281    float backupDuration = fStatsPeriodDuration;
     1282    fStatsPeriodDuration = evt.GetFloat();
     1283    if (fStatsPeriodDuration < 0)
     1284    {
     1285        Error("Statistics period duration should be greater than zero. Discarding provided value.");
     1286        fStatsPeriodDuration = backupDuration;
     1287        return GetCurrentState();   
     1288    }
     1289    if (fStatsPeriodDuration != fStatsPeriodDuration)
     1290    {
     1291        Error("Provided duration does not appear to be a valid float. discarding it.");
     1292        fStatsPeriodDuration = backupDuration;
     1293        return GetCurrentState();   
     1294    }
     1295    if (backupDuration == fStatsPeriodDuration)
     1296        Warn("Warning: statistics period was not modified: supplied value already in use");
     1297    else
     1298    {
     1299        if (fStatsPeriodDuration == 0.0f)
     1300            Message("Statistics are now OFF");
     1301        else
     1302        {
     1303            stringstream str;
     1304            str << "Statistics period is now " << fStatsPeriodDuration << " seconds";
     1305            Message(str.str());     
     1306        }   
     1307    }
     1308    return GetCurrentState();
    13321309}
    13331310// --------------------------------------------------------------------------
     
    13351312//! set the opened files service on or off.
    13361313//! @param evt
    1337 //!             the current event. contains the instruction string. similar to setdebugonoff
     1314//!        the current event. contains the instruction string. similar to setdebugonoff
    13381315//! @returns
    1339 //!             the new state. Which, in that case, is the current state
     1316//!        the new state. Which, in that case, is the current state
    13401317//!
    13411318int DataLogger::SetOpenedFilesOnOff(const Event& evt)
    13421319{
    1343         bool backupOpened = fOpenedFilesIsOn;
    1344         fOpenedFilesIsOn = evt.GetBool();
    1345         if (fOpenedFilesIsOn == backupOpened)
    1346                 Warn("Warning: opened files service mode was already in the requested state");
    1347         else
    1348         {
    1349                 stringstream str;
    1350                 str << "Opened files service mode is now " << fOpenedFilesIsOn;
    1351                 Message(str.str());
    1352         }
    1353         return GetCurrentState();
    1354        
     1320    bool backupOpened = fOpenedFilesIsOn;
     1321    fOpenedFilesIsOn = evt.GetBool();
     1322    if (fOpenedFilesIsOn == backupOpened)
     1323        Warn("Warning: opened files service mode was already in the requested state");
     1324    else
     1325    {
     1326        stringstream str;
     1327        str << "Opened files service mode is now " << fOpenedFilesIsOn;
     1328        Message(str.str());
     1329    }
     1330    return GetCurrentState();
     1331   
    13551332}
    13561333// --------------------------------------------------------------------------
     
    13581335//! set the number of subscriptions and opened fits on and off
    13591336//! @param evt
    1360 //!             the current event. contains the instruction string. similar to setdebugonoff
     1337//!        the current event. contains the instruction string. similar to setdebugonoff
    13611338//! @returns
    1362 //!             the new state. Which, in that case, is the current state
     1339//!        the new state. Which, in that case, is the current state
    13631340//!
    13641341int DataLogger::SetNumSubsAndFitsOnOff(const Event& evt)
    13651342{
    1366         bool backupSubs = fNumSubAndFitsIsOn;
    1367         fNumSubAndFitsIsOn = evt.GetBool();
    1368         if (fNumSubAndFitsIsOn == backupSubs)
    1369                 Warn("Warning: Number of subscriptions service mode was already in the requested state");
    1370         else
    1371         {
    1372                 stringstream str;
    1373                 str << "Number of subscriptions service mode is now " << fNumSubAndFitsIsOn;
    1374                 Message(str.str());
    1375         }
    1376         return GetCurrentState();
    1377 }
    1378 // --------------------------------------------------------------------------
    1379 //
    1380 //!     Sets the path to use for the Nightly log file.
     1343    bool backupSubs = fNumSubAndFitsIsOn;
     1344    fNumSubAndFitsIsOn = evt.GetBool();
     1345    if (fNumSubAndFitsIsOn == backupSubs)
     1346        Warn("Warning: Number of subscriptions service mode was already in the requested state");
     1347    else
     1348    {
     1349        stringstream str;
     1350        str << "Number of subscriptions service mode is now " << fNumSubAndFitsIsOn;
     1351        Message(str.str());
     1352    }
     1353    return GetCurrentState();
     1354}
     1355// --------------------------------------------------------------------------
     1356//
     1357//!    Sets the path to use for the Nightly log file.
    13811358//! @param evt
    1382 //!     the event transporting the path
     1359//!     the event transporting the path
    13831360//! @returns
    1384 //!             currently only the current state.
     1361//!        currently only the current state.
    13851362//
    13861363int DataLogger::ConfigureNightlyFileName(const Event& evt)
    13871364{
    1388         if (evt.GetText() != NULL)
    1389         {
    1390                 fNightlyFileName = std::string(evt.GetText()); 
    1391                 Message("New Nightly folder specified: " + fNightlyFileName);
    1392         }
    1393         else
    1394                 Error("Empty Nightly folder given. Please specify a valid path.");
    1395 
    1396         return GetCurrentState();
     1365    if (evt.GetText() != NULL)
     1366    {
     1367        fNightlyFileName = string(evt.GetText());
     1368        Message("New Nightly folder specified: " + fNightlyFileName);
     1369    }
     1370    else
     1371        Error("Empty Nightly folder given. Please specify a valid path.");
     1372
     1373    return GetCurrentState();
    13971374}
    13981375// --------------------------------------------------------------------------
     
    14001377//! Sets the path to use for the run log file.
    14011378//! @param evt
    1402 //!             the event transporting the path
     1379//!        the event transporting the path
    14031380//! @returns
    1404 //!     currently only the current state
     1381//!     currently only the current state
    14051382int DataLogger::ConfigureRunFileName(const Event& evt)
    14061383{
    1407         if (evt.GetText() != NULL)
    1408         {
    1409                 fRunFileName = std::string(evt.GetText());
    1410                 Message("New Run folder specified: " + fRunFileName);
    1411         }
    1412         else
    1413                 Error("Empty Nightly folder given. Please specify a valid path");
    1414 
    1415         return GetCurrentState();
     1384    if (evt.GetText() != NULL)
     1385    {
     1386        fRunFileName = string(evt.GetText());
     1387        Message("New Run folder specified: " + fRunFileName);
     1388    }
     1389    else
     1390        Error("Empty Nightly folder given. Please specify a valid path");
     1391
     1392    return GetCurrentState();
    14161393}
    14171394// --------------------------------------------------------------------------
     
    14191396//! Sets the run number.
    14201397//! @param evt
    1421 //!             the event transporting the run number
     1398//!        the event transporting the run number
    14221399//! @returns
    1423 //!     currently only the current state
    1424 //TODO remove this function as the run numbers will be distributed through a dedicated service
     1400//!     currently only the current state
    14251401int DataLogger::ConfigureRunNumber(const Event& evt)
    14261402{
    1427         fRunNumber = evt.GetInt();
    1428         std::stringstream str;
    1429         str << "The new run number is: " << fRunNumber;
    1430         Message(str.str());
    1431         return GetCurrentState();
     1403    fRunNumber = evt.GetInt();
     1404    stringstream str;
     1405    str << "The new run number is: " << fRunNumber;
     1406    Message(str.str());
     1407    return GetCurrentState();
    14321408}
    14331409// --------------------------------------------------------------------------
     
    14351411//! Notifies the DIM service that a particular file was opened
    14361412//! @ param name the base name of the opened file, i.e. without path nor extension.
    1437 //!     WARNING: use string instead of string& because I pass values that do not convert to string&.
    1438 //!             this is not a problem though because file are not opened so often.
     1413//!     WARNING: use string instead of string& because I pass values that do not convert to string&.
     1414//!        this is not a problem though because file are not opened so often.
    14391415//! @ param type the type of the opened file. 0 = none open, 1 = log, 2 = text, 4 = fits
    1440 inline void DataLogger::NotifyOpenedFile(std::string name, int type, DimDescribedService* service)
    1441 {
    1442         if (fOpenedFilesIsOn)
    1443         {
    1444                 if (fDebugIsOn)
    1445                 {
    1446                         stringstream str;
    1447                         str << "Updating files service " << service->getName() << "with code: " << type << " and file: " << name;
    1448                         Debug(str.str());
    1449                         str.str("");
    1450                         str << "Num subs: " << fNumSubAndFitsData.numSubscriptions << " Num open FITS: " << fNumSubAndFitsData.numOpenFits;
    1451                         Debug(str.str());
    1452                 }
    1453                 OpenFileToDim fToDim;
    1454                 fToDim.code = type;
    1455                 memcpy(fToDim.fileName, name.c_str(), name.size()+1);
    1456                 service->setData(reinterpret_cast<void*>(&fToDim), name.size()+1+sizeof(int));
    1457                 service->setQuality(0);
    1458                 service->updateService();
    1459         }
     1416inline void DataLogger::NotifyOpenedFile(string name, int type, DimDescribedService* service)
     1417{
     1418    if (fOpenedFilesIsOn)
     1419    {
     1420        if (fDebugIsOn)
     1421        {
     1422            stringstream str;
     1423            str << "Updating files service " << service->getName() << "with code: " << type << " and file: " << name;
     1424            Debug(str.str());
     1425            str.str("");
     1426            str << "Num subs: " << fNumSubAndFitsData.numSubscriptions << " Num open FITS: " << fNumSubAndFitsData.numOpenFits;
     1427            Debug(str.str());
     1428        }
     1429        OpenFileToDim fToDim;
     1430        fToDim.code = type;
     1431        memcpy(fToDim.fileName, name.c_str(), name.size()+1);
     1432        service->setData(reinterpret_cast<void*>(&fToDim), name.size()+1+sizeof(int));
     1433        service->setQuality(0);
     1434        service->updateService();
     1435    }
    14601436}
    14611437// --------------------------------------------------------------------------
     
    14651441//! and tries to open it.
    14661442//! @returns
    1467 //!             kSM_NightlyOpen if success, kSM_BadNightlyConfig if failure
     1443//!        kSM_NightlyOpen if success, kSM_BadNightlyConfig if failure
    14681444int DataLogger::StartPlease()
    14691445{
    1470         if (fDebugIsOn)
    1471         {
    1472                 Debug("Starting...");   
    1473         }
    1474         Time time;
    1475         std::stringstream sTime;
    1476         sTime << time.Y() << "_" << time.M() << "_" << time.D();
    1477 
    1478         fFullNightlyLogFileName = fNightlyFileName + '/' + sTime.str() + ".log";
    1479         fNightlyLogFile.open(fFullNightlyLogFileName.c_str(), std::ios_base::out | std::ios_base::app);
    1480         if (errno != 0)
    1481         {
    1482                 std::stringstream str;
    1483                 str << "Unable to open Nightly Log " << fFullNightlyLogFileName << ". Reason: " << strerror(errno) << " [" << errno << "]";
    1484                 Error(str);     
    1485         }
    1486         fFullNightlyReportFileName = fNightlyFileName + '/' + sTime.str() + ".rep";
    1487         fNightlyReportFile.open(fFullNightlyReportFileName.c_str(), std::ios_base::out | std::ios_base::app);
    1488         if (errno != 0)
    1489         {
    1490                 std::stringstream str;
    1491                 str << "Unable to open Nightly Report " << fFullNightlyReportFileName << ". Reason: " << strerror(errno) << " [" << errno << "]";
    1492                 Error(str);     
    1493         }
    1494 
    1495         if (!fNightlyLogFile.is_open() || !fNightlyReportFile.is_open())
    1496         {       
    1497                 //TODO send an error message   
    1498             return kSM_BadNightlyConfig;
    1499         }
    1500         //get the size of the newly opened file.
    1501         struct stat st;
    1502         stat(fFullNightlyLogFileName.c_str(), &st);
    1503         fBaseSizeNightly = st.st_size; 
    1504         stat(fFullNightlyReportFileName.c_str(), &st);
    1505         fBaseSizeNightly += st.st_size;
    1506         fFileSizesMap.clear();
    1507         fBaseSizeRun = 0;
    1508         fPreviousSize = 0;
    1509         //notify that files were opened
    1510         std::string actualTargetDir;
    1511         if (fNightlyFileName == ".")
    1512         {
    1513                 char currentPath[FILENAME_MAX];
    1514                 if (!getcwd(currentPath, sizeof(currentPath)))
    1515                 {
    1516                     if (errno != 0)
    1517                     {
    1518                         std::stringstream str;
    1519                         str << "Unable retrieve current path" << ". Reason: " << strerror(errno) << " [" << errno << "]";
    1520                         Error(str);
    1521                     }
    1522                 }
    1523                 actualTargetDir = currentPath;
    1524         }
    1525         else
    1526         {
    1527                 actualTargetDir = fNightlyFileName;     
    1528         }
    1529         //notify that a new file has been opened.
    1530         NotifyOpenedFile(actualTargetDir + '/' + sTime.str(), 3, fOpenedNightlyFiles);
    1531 
    1532         fOpenedNightlyFits.clear();
    1533        
    1534         return kSM_NightlyOpen;         
     1446    if (fDebugIsOn)
     1447    {
     1448        Debug("Starting...");   
     1449    }
     1450    Time time;
     1451    stringstream sTime;
     1452    sTime << time.Y() << "_" << time.M() << "_" << time.D();
     1453
     1454    fFullNightlyLogFileName = fNightlyFileName + '/' + sTime.str() + ".log";
     1455    fNightlyLogFile.open(fFullNightlyLogFileName.c_str(), ios_base::out | ios_base::app);
     1456    if (errno != 0)
     1457    {
     1458        stringstream str;
     1459        str << "Unable to open Nightly Log " << fFullNightlyLogFileName << ". Reason: " << strerror(errno) << " [" << errno << "]";
     1460        Error(str);   
     1461    }
     1462    fFullNightlyReportFileName = fNightlyFileName + '/' + sTime.str() + ".rep";
     1463    fNightlyReportFile.open(fFullNightlyReportFileName.c_str(), ios_base::out | ios_base::app);
     1464    if (errno != 0)
     1465    {
     1466        stringstream str;
     1467        str << "Unable to open Nightly Report " << fFullNightlyReportFileName << ". Reason: " << strerror(errno) << " [" << errno << "]";
     1468        Error(str);   
     1469    }
     1470
     1471    if (!fNightlyLogFile.is_open() || !fNightlyReportFile.is_open())
     1472    {   
     1473        stringstream str;
     1474        str << "Something went wrong while openning nightly files " << fFullNightlyLogFileName << " and " << fFullNightlyReportFileName;
     1475        Error(str.str());
     1476        return kSM_BadNightlyConfig;
     1477    }
     1478    //get the size of the newly opened file.
     1479    struct stat st;
     1480    stat(fFullNightlyLogFileName.c_str(), &st);
     1481    fBaseSizeNightly = st.st_size;   
     1482    stat(fFullNightlyReportFileName.c_str(), &st);
     1483    fBaseSizeNightly += st.st_size;
     1484    fFileSizesMap.clear();
     1485    fBaseSizeRun = 0;
     1486    fPreviousSize = 0;
     1487    //notify that files were opened
     1488    string actualTargetDir;
     1489    if (fNightlyFileName == ".")
     1490    {
     1491        char currentPath[FILENAME_MAX];
     1492        if (!getcwd(currentPath, sizeof(currentPath)))
     1493        {
     1494            if (errno != 0)
     1495            {
     1496                stringstream str;
     1497                str << "Unable retrieve current path" << ". Reason: " << strerror(errno) << " [" << errno << "]";
     1498                Error(str);
     1499            }
     1500        }
     1501        actualTargetDir = currentPath;
     1502    }
     1503    else
     1504    {
     1505        actualTargetDir = fNightlyFileName;   
     1506    }
     1507    //notify that a new file has been opened.
     1508    NotifyOpenedFile(actualTargetDir + '/' + sTime.str(), 3, fOpenedNightlyFiles);
     1509
     1510    fOpenedNightlyFits.clear();
     1511   
     1512    return kSM_NightlyOpen;     
    15351513}
    15361514
     
    15401518//! open if required a the FITS files corresponding to a given subscription
    15411519//! @param sub
    1542 //!     the current DimInfo subscription being examined
     1520//!     the current DimInfo subscription being examined
    15431521void DataLogger::OpenFITSFilesPlease(SubscriptionType& sub)
    15441522{
    1545         std::string serviceName(sub.dimInfo->getName());
    1546         for (unsigned int i=0;i<serviceName.size(); i++)
    1547         {
    1548                 if (serviceName[i] == '/')
    1549                 {
    1550                         serviceName[i] = '_';
    1551                         break; 
    1552                 }       
    1553         }
    1554         Time time;
    1555         std::stringstream sTime;
    1556         sTime << time.Y() << "_" << time.M() << "_" << time.D();
    1557         //we open the NightlyFile anyway, otherwise this function shouldn't have been called.
    1558         if (!sub.nightlyFile.IsOpen())
    1559         {
    1560             std::string fileNameOnly = sTime.str() + '_' + serviceName + ".fits";
    1561                 std::string partialName = fNightlyFileName + '/' + fileNameOnly;
    1562                 AllocateFITSBuffers(sub);
    1563                 //get the size of the file we're about to open
    1564                 if (fFileSizesMap.find(partialName) == fFileSizesMap.end())
    1565                 {
    1566                         struct stat st;
    1567                         if (!stat(partialName.c_str(), &st))
    1568                                 fBaseSizeNightly += st.st_size;
    1569                         fFileSizesMap[partialName] = 0;
    1570                         //remember that this file was opened.
    1571                         fOpenedNightlyFits[fileNameOnly] =  serviceName;
    1572                 }
    1573                 sub.nightlyFile.Open(partialName, serviceName, NULL, &fNumSubAndFitsData.numOpenFits, this);//Out());
    1574 
    1575                 //notify the opening
    1576                 std::string actualTargetDir;
    1577                 if (fNightlyFileName == ".")
    1578                 {
    1579                         char currentPath[FILENAME_MAX];
    1580                         if (getcwd(currentPath, sizeof(currentPath)))
    1581                             actualTargetDir = currentPath;
    1582                 }
    1583                 else
    1584                 {
    1585                         actualTargetDir = fNightlyFileName;     
    1586                 }               
    1587                 NotifyOpenedFile(actualTargetDir + '/' + sTime.str(), 7, fOpenedNightlyFiles);
    1588                 if (fNumSubAndFitsIsOn)
    1589                         fNumSubAndFits->updateService();
    1590                 if (fDebugIsOn)
    1591                 {
    1592                         stringstream str;
    1593                         str << "Opened Nightly FITS: " << partialName << " and table: FACT-" << serviceName << ".current number of opened FITS: " << fNumSubAndFitsData.numOpenFits;
    1594                         Debug(str.str());       
    1595                 }
    1596         }
    1597         if (!sub.runFile.IsOpen() && (GetCurrentState() == kSM_Logging))
    1598         {//buffer for the run file have already been allocated when doing the Nightly file
    1599                 std::stringstream sRun;
    1600                 sRun << fRunNumber;
    1601 #ifdef ONE_RUN_FITS_ONLY
    1602                 std::string fileNameOnly = sRun.str() + ".fits";
    1603                 std::string partialName = fRunFileName + '/' + fileNameOnly;
    1604                 if (fRunFitsFile == NULL)
    1605                 {
    1606 #else
    1607                 std::string fileNameOnly = sRun.str() + '_' + serviceName + ".fits";
    1608                 std::string partialName = fRunFileName + '/' + fileNameOnly;
    1609 #endif
    1610                         //get the size of the file we're about to open
    1611                         if (fFileSizesMap.find(partialName) == fFileSizesMap.end())
    1612                         {
    1613                                 struct stat st;
    1614                                 if (!stat(partialName.c_str(), &st))
    1615                                         fBaseSizeRun += st.st_size;
    1616                                 else
    1617                                         fBaseSizeRun = 0;
    1618                                 fFileSizesMap[partialName] = 0;
    1619                                 fOpenedRunFits[fileNameOnly] = serviceName;
    1620                         }
    1621 #ifdef ONE_RUN_FITS_ONLY
    1622                         try
    1623                         {
    1624                                 fRunFitsFile = new CCfits::FITS(partialName, CCfits::RWmode::Write);
    1625                                 (fNumSubAndFitsData.numOpenFits)++;
    1626                         }       
    1627                         catch (CCfits::FitsError e)
    1628                         {
    1629                                 std::stringstream str;
    1630                                 str << "Could not open FITS Run file " << partialName << " reason: " << e.message();
    1631                                 Error(str);
    1632                                 fRunFitsFile = NULL;
    1633                         }
    1634 #endif
    1635                         std::string actualTargetDir;
    1636                         if (fRunFileName == ".")
    1637                         {
    1638                                 char currentPath[FILENAME_MAX];
    1639                                 if (getcwd(currentPath, sizeof(currentPath)))
    1640                                     actualTargetDir = currentPath;
    1641                         }
    1642                         else
    1643                         {
    1644                                 actualTargetDir = fRunFileName;
    1645                         }               
    1646                         NotifyOpenedFile(actualTargetDir + '/' + sRun.str(), 7, fOpenedRunFiles);// + '_' + serviceName, 4);
    1647 #ifdef ONE_RUN_FITS_ONLY
    1648                 }
    1649                 sub.runFile.Open(partialName, serviceName, fRunFitsFile, &fNumSubAndFitsData.numOpenFits, this);//Out());
    1650 #else
    1651                 sub.runFile.Open(partialName, serviceName, NULL, &fNumSubAndFitsData.numOpenFits, this);//Out());
    1652 #endif //one_run_fits_only
    1653            if (fNumSubAndFitsIsOn)
    1654                    fNumSubAndFits->updateService();
    1655                 if (fDebugIsOn)
    1656                 {
    1657                         stringstream str;
    1658                         str << "Opened Run FITS: " << partialName << " and table: FACT-" << serviceName << ".current number of opened FITS: " << fNumSubAndFitsData.numOpenFits;
    1659                         Debug(str.str());       
    1660                 }
    1661         }
    1662 }       
     1523    string serviceName(sub.dimInfo->getName());
     1524    //we must check if we should group this service subscription to a single fits file before we replace the / by _
     1525    bool hasGrouping = false;
     1526    if (!sub.runFile.IsOpen() && (GetCurrentState() == kSM_Logging))
     1527    {//will we find this service in the grouping list ?
     1528        for (set<string>::iterator it=fGrouping.begin(); it!=fGrouping.end(); it++)
     1529        {
     1530            if (serviceName.find(*it) != string::npos)
     1531            {
     1532                hasGrouping = true;
     1533                break;
     1534            }
     1535        }
     1536    }
     1537    for (unsigned int i=0;i<serviceName.size(); i++)
     1538    {
     1539        if (serviceName[i] == '/')
     1540        {
     1541            serviceName[i] = '_';
     1542            break;   
     1543        }   
     1544    }
     1545    Time time;
     1546    stringstream sTime;
     1547    sTime << time.Y() << "_" << time.M() << "_" << time.D();
     1548    //we open the NightlyFile anyway, otherwise this function shouldn't have been called.
     1549    if (!sub.nightlyFile.IsOpen())
     1550    {
     1551        string fileNameOnly = sTime.str() + '_' + serviceName + ".fits";
     1552        string partialName = fNightlyFileName + '/' + fileNameOnly;
     1553        AllocateFITSBuffers(sub);
     1554        //get the size of the file we're about to open
     1555        if (fFileSizesMap.find(partialName) == fFileSizesMap.end())
     1556        {
     1557            struct stat st;
     1558            if (!stat(partialName.c_str(), &st))
     1559                fBaseSizeNightly += st.st_size;
     1560            fFileSizesMap[partialName] = 0;
     1561            //remember that this file was opened.
     1562            fOpenedNightlyFits[fileNameOnly].push_back(serviceName);
     1563        }
     1564        sub.nightlyFile.Open(partialName, serviceName, NULL, &fNumSubAndFitsData.numOpenFits, this);//Out());
     1565
     1566        //notify the opening
     1567        string actualTargetDir;
     1568        if (fNightlyFileName == ".")
     1569        {
     1570            char currentPath[FILENAME_MAX];
     1571            if (getcwd(currentPath, sizeof(currentPath)))
     1572                actualTargetDir = currentPath;
     1573        }
     1574        else
     1575        {
     1576            actualTargetDir = fNightlyFileName;   
     1577        }       
     1578        NotifyOpenedFile(actualTargetDir + '/' + sTime.str(), 7, fOpenedNightlyFiles);
     1579        if (fNumSubAndFitsIsOn)
     1580            fNumSubAndFits->updateService();
     1581        if (fDebugIsOn)
     1582        {
     1583            stringstream str;
     1584            str << "Opened Nightly FITS: " << partialName << " and table: FACT-" << serviceName << ".current number of opened FITS: " << fNumSubAndFitsData.numOpenFits;
     1585            Debug(str.str());   
     1586        }
     1587    }
     1588    if (!sub.runFile.IsOpen() && (GetCurrentState() == kSM_Logging))
     1589    {//buffer for the run file have already been allocated when doing the Nightly file
     1590        stringstream sRun;
     1591        sRun << fRunNumber;
     1592        string fileNameOnly;
     1593        string partialName;
     1594
     1595        if (hasGrouping)
     1596        {
     1597            fileNameOnly = sRun.str() + "_group.fits";
     1598            partialName = fRunFileName + '/' + fileNameOnly;
     1599        }
     1600        else
     1601        {
     1602            fileNameOnly = sRun.str() + '_' + serviceName + ".fits";
     1603            partialName = fRunFileName + '/' + fileNameOnly;
     1604        }
     1605        //get the size of the file we're about to open
     1606        if (fFileSizesMap.find(partialName) == fFileSizesMap.end())
     1607        {
     1608            struct stat st;
     1609            if (!stat(partialName.c_str(), &st))
     1610                fBaseSizeRun += st.st_size;
     1611            else
     1612                fBaseSizeRun = 0;
     1613            fFileSizesMap[partialName] = 0;
     1614            fOpenedRunFits[fileNameOnly].push_back(serviceName);
     1615        }
     1616        else
     1617            if (hasGrouping)
     1618            {//most likely I should add this service name.
     1619             //the only case for which I should not add it is if a service disapeared, hence the file was closed
     1620             //and reopened again. Unlikely to happen, but well it may
     1621                bool found = false;
     1622                for (vector<string>::iterator it=fOpenedRunFits[fileNameOnly].begin(); it!=fOpenedRunFits[fileNameOnly].end(); it++)
     1623                    if (*it == serviceName)
     1624                    {
     1625                        found = true;
     1626                        break;
     1627                    }
     1628                if (!found)
     1629                    fOpenedRunFits[fileNameOnly].push_back(serviceName);
     1630            }
     1631        if (hasGrouping && fRunFitsFile == NULL)
     1632            try
     1633            {
     1634                fRunFitsFile = new CCfits::FITS(partialName, CCfits::RWmode::Write);
     1635                (fNumSubAndFitsData.numOpenFits)++;
     1636            }   
     1637            catch (CCfits::FitsError e)
     1638            {
     1639                stringstream str;
     1640                str << "Could not open FITS Run file " << partialName << " reason: " << e.message();
     1641                Error(str);
     1642                fRunFitsFile = NULL;
     1643            }
     1644
     1645        string actualTargetDir;
     1646        if (fRunFileName == ".")
     1647        {
     1648            char currentPath[FILENAME_MAX];
     1649            if (getcwd(currentPath, sizeof(currentPath)))
     1650                actualTargetDir = currentPath;
     1651        }
     1652        else
     1653        {
     1654           actualTargetDir = fRunFileName;
     1655        }
     1656        NotifyOpenedFile(actualTargetDir + '/' + sRun.str(), 7, fOpenedRunFiles);// + '_' + serviceName, 4);
     1657        if (hasGrouping)
     1658            sub.runFile.Open(partialName, serviceName, fRunFitsFile, &fNumSubAndFitsData.numOpenFits, this);//Out());
     1659        else
     1660            sub.runFile.Open(partialName, serviceName, NULL, &fNumSubAndFitsData.numOpenFits, this);//Out());
     1661
     1662       if (fNumSubAndFitsIsOn)
     1663           fNumSubAndFits->updateService();
     1664           if (fDebugIsOn)
     1665        {
     1666            stringstream str;
     1667            str << "Opened Run FITS: " << partialName << " and table: FACT-" << serviceName << ".current number of opened FITS: " << fNumSubAndFitsData.numOpenFits;
     1668            Debug(str.str());   
     1669        }
     1670    }
     1671}   
    16631672// --------------------------------------------------------------------------
    16641673//
    16651674void DataLogger::AllocateFITSBuffers(SubscriptionType& sub)
    16661675{
    1667         int size = sub.dimInfo->getSize();
    1668        
    1669         //Init the time columns of the file
    1670         Description dateDesc(std::string("Time"), std::string("Modified Julian Date"), std::string("MjD"));
    1671         sub.nightlyFile.AddStandardColumn(dateDesc, "1D", &fMjD, sizeof(double));
    1672         sub.runFile.AddStandardColumn(dateDesc, "1D", &fMjD, sizeof(double));
    1673 
    1674         Description QoSDesc("Qos", "Quality of service", "None");
    1675         sub.nightlyFile.AddStandardColumn(QoSDesc, "1J", &fQuality, sizeof(int));
    1676         sub.runFile.AddStandardColumn(QoSDesc, "1J", &fQuality, sizeof(int));
    1677 
    1678         const Converter::FormatList flist = sub.fConv->GetList();
     1676    int size = sub.dimInfo->getSize();
     1677   
     1678    //Init the time columns of the file
     1679    Description dateDesc(string("Time"), string("Modified Julian Date"), string("MjD"));
     1680    sub.nightlyFile.AddStandardColumn(dateDesc, "1D", &fMjD, sizeof(double));
     1681    sub.runFile.AddStandardColumn(dateDesc, "1D", &fMjD, sizeof(double));
     1682
     1683    Description QoSDesc("Qos", "Quality of service", "None");
     1684    sub.nightlyFile.AddStandardColumn(QoSDesc, "1J", &fQuality, sizeof(int));
     1685    sub.runFile.AddStandardColumn(QoSDesc, "1J", &fQuality, sizeof(int));
     1686
     1687    const Converter::FormatList flist = sub.fConv->GetList();
    16791688    // Compilation failed
    16801689    if (flist.empty() || flist.back().first.second!=0)
    16811690    {
    1682         Error("Compilation of format string failed.");
     1691        Error("Compilation of format string failed.");
    16831692        return;
    16841693    }
    16851694
    1686         //we've got a nice structure describing the format of this service's messages.
    1687         //Let's create the appropriate FITS columns
    1688         std::vector<std::string> dataFormatsLocal;
    1689         for (unsigned int i=0;i<flist.size()-1;i++)
    1690         {
    1691                 std::stringstream dataQualifier;
    1692 
    1693                 dataQualifier << flist[i].second.first;
    1694                 switch (flist[i].first.first->name()[0])
    1695                 {//TODO handle all the data format cases
    1696                         case 'c':
    1697                         case 'C':
    1698                                 dataQualifier.str("S");
    1699                         break;
    1700                         case 's':
    1701                                 dataQualifier << "I";
    1702                         break;
    1703                         case 'i':
    1704                         case 'I':
    1705                                 dataQualifier << "J";
    1706                         break;
    1707                         case 'l':
    1708                         case 'L':
    1709                                 dataQualifier << "J";
    1710                                 //TODO triple check that in FITS, long = int
    1711                         break;
    1712                         case 'f':
    1713                         case 'F':
    1714                                 dataQualifier << "E";
    1715                         break;
    1716                         case 'd':
    1717                         case 'D':
    1718                                 dataQualifier << "D";
    1719                         break;
    1720                         case 'x':
    1721                         case 'X':
    1722                                 dataQualifier << "K";
    1723                         break;
    1724                         case 'S':
    1725                                 //for strings, the number of elements I get is wrong. Correct it
    1726                                 dataQualifier.str(""); //clear
    1727                                 dataQualifier << size-1 <<  "A";
    1728                                 size = size-1;
    1729                         break;
    1730                        
    1731                         default:
    1732                                 Fatal("THIS SHOULD NEVER BE REACHED. dataLogger.cc ln 1198.");
    1733                 };
    1734                 //we skip the variable length strings for now (in fits only)
    1735                 if (dataQualifier.str() != "S")
    1736                         dataFormatsLocal.push_back(dataQualifier.str());
    1737          }
    1738          sub.nightlyFile.InitDataColumns(fServiceList.GetDescriptions(sub.dimInfo->getName()), dataFormatsLocal, sub.dimInfo->getData(), size);
    1739          sub.runFile.InitDataColumns(fServiceList.GetDescriptions(sub.dimInfo->getName()), dataFormatsLocal, sub.dimInfo->getData(), size);
     1695    //we've got a nice structure describing the format of this service's messages.
     1696    //Let's create the appropriate FITS columns
     1697    vector<string> dataFormatsLocal;
     1698    for (unsigned int i=0;i<flist.size()-1;i++)
     1699    {
     1700         stringstream dataQualifier;
     1701
     1702         dataQualifier << flist[i].second.first;
     1703         switch (flist[i].first.first->name()[0])
     1704         {
     1705             case 'c':
     1706             case 'C':
     1707                 dataQualifier.str("S");
     1708             break;
     1709             case 's':
     1710                 dataQualifier << "I";
     1711             break;
     1712             case 'i':
     1713             case 'I':
     1714                 dataQualifier << "J";
     1715             break;
     1716             case 'l':
     1717             case 'L':
     1718                 dataQualifier << "J";
     1719             break;
     1720             case 'f':
     1721             case 'F':
     1722                 dataQualifier << "E";
     1723             break;
     1724             case 'd':
     1725             case 'D':
     1726                 dataQualifier << "D";
     1727             break;
     1728             case 'x':
     1729             case 'X':
     1730                 dataQualifier << "K";
     1731             break;
     1732             case 'S':
     1733                 //for strings, the number of elements I get is wrong. Correct it
     1734                 dataQualifier.str(""); //clear
     1735                 dataQualifier << size-1 <<  "A";
     1736                 size = size-1;
     1737             break;
     1738             
     1739             default:
     1740                 Fatal("THIS SHOULD NEVER BE REACHED. dataLogger.cc ln 1198.");
     1741         };
     1742         //we skip the variable length strings for now (in fits only)
     1743         if (dataQualifier.str() != "S")
     1744             dataFormatsLocal.push_back(dataQualifier.str());
     1745     }
     1746     sub.nightlyFile.InitDataColumns(fServiceList.GetDescriptions(sub.dimInfo->getName()), dataFormatsLocal, sub.dimInfo->getData(), size);
     1747     sub.runFile.InitDataColumns(fServiceList.GetDescriptions(sub.dimInfo->getName()), dataFormatsLocal, sub.dimInfo->getData(), size);
    17401748}
    17411749// --------------------------------------------------------------------------
     
    17451753void DataLogger::WriteToFITS(SubscriptionType& sub)
    17461754{
    1747                 //nightly File status (open or not) already checked
    1748                 if (sub.nightlyFile.IsOpen())
    1749                 {
    1750                         sub.nightlyFile.Write(sub.fConv);
    1751                         if (fDebugIsOn)
    1752                         {
    1753                                 Debug("Writing to nightly FITS " + sub.nightlyFile.fFileName); 
    1754                         }
    1755                 }
    1756                 if (sub.runFile.IsOpen())
    1757                 {
    1758                         sub.runFile.Write(sub.fConv);
    1759                         if (fDebugIsOn)
    1760                         {
    1761                                 Debug("Writing to Run FITS " + sub.runFile.fFileName); 
    1762                         }
    1763                 }
     1755        //nightly File status (open or not) already checked
     1756        if (sub.nightlyFile.IsOpen())
     1757        {
     1758            sub.nightlyFile.Write(sub.fConv);
     1759            if (fDebugIsOn)
     1760            {
     1761                Debug("Writing to nightly FITS " + sub.nightlyFile.fFileName);   
     1762            }
     1763        }
     1764        if (sub.runFile.IsOpen())
     1765        {
     1766            sub.runFile.Write(sub.fConv);
     1767            if (fDebugIsOn)
     1768            {
     1769                Debug("Writing to Run FITS " + sub.runFile.fFileName);   
     1770            }
     1771        }
    17641772}
    17651773#endif //if has_fits
     
    17701778//! and tries to open it.
    17711779//! @returns
    1772 //!             kSM_Logging if success, kSM_BadRunConfig if failure.
     1780//!        kSM_Logging if success, kSM_BadRunConfig if failure.
    17731781int DataLogger::StartRunPlease()
    17741782{
    1775         if (fDebugIsOn)
    1776         {
    1777                 Debug("Starting Run Logging...");       
    1778         }
    1779         //attempt to open run file with current parameters
    1780 //      if (fRunNumber == -1)
    1781 //              return kSM_BadRunConfig;
    1782         std::stringstream sRun;
    1783         sRun << fRunNumber;
    1784         fFullRunLogFileName = fRunFileName + '/' + sRun.str() + ".log";
    1785         fRunLogFile.open(fFullRunLogFileName.c_str(), std::ios_base::out | std::ios_base::app); //maybe should be app instead of ate
    1786         if (errno != 0)
    1787         {
    1788                 std::stringstream str;
    1789                 str << "Unable to open run Log " << fFullRunLogFileName << ". Reason: " << strerror(errno) << " [" << errno << "]";
    1790                 Error(str);     
    1791         }
    1792         fFullRunReportFileName = fRunFileName + '/' + sRun.str() + ".rep";
    1793         fRunReportFile.open(fFullRunReportFileName.c_str(), std::ios_base::out | std::ios_base::app);
    1794         if (errno != 0)
    1795         {
    1796                 std::stringstream str;
    1797                 str << "Unable to open run report " << fFullRunReportFileName << ". Reason: " << strerror(errno) << " [" << errno << "]";
    1798                 Error(str);     
    1799         }
    1800        
    1801         if (!fRunLogFile.is_open() || !fRunReportFile.is_open())
    1802         {
    1803                 //TODO send an error message
    1804                 return kSM_BadRunConfig;       
    1805         }
    1806         //get the size of the newly opened file.
    1807         struct stat st;
    1808         fBaseSizeRun = 0;
    1809         if (fFileSizesMap.find(fFullRunLogFileName) == fFileSizesMap.end())
    1810         {
    1811                 stat(fFullRunLogFileName.c_str(), &st);
    1812                 if (errno != 0)
    1813                 {
    1814                         std::stringstream str;
    1815                         str << "Unable to stat " << fFullRunLogFileName << ". Reason: " << strerror(errno) << " [" << errno << "]";
    1816                         Error(str);     
    1817                 }
    1818                 else
    1819                         fBaseSizeRun += st.st_size;
    1820                 fFileSizesMap[fFullRunLogFileName] = 0;
    1821         }
    1822         if (fFileSizesMap.find(fFullRunReportFileName) == fFileSizesMap.end())
    1823         {
    1824                 stat(fFullRunReportFileName.c_str(), &st);
    1825                 if (errno != 0)
    1826                 {
    1827                         std::stringstream str;
    1828                         str << "Unable to stat " << fFullRunReportFileName << ". Reason: " << strerror(errno) << " [" << errno << "]";
    1829                         Error(str);     
    1830                 }
    1831                 else
    1832                         fBaseSizeRun += st.st_size;
    1833                 fFileSizesMap[fFullRunReportFileName] = 0;
    1834         }
    1835         std::string actualTargetDir;
    1836         if (fRunFileName == ".")
    1837         {
    1838                 char currentPath[FILENAME_MAX];
    1839                 if (!getcwd(currentPath, sizeof(currentPath)))
    1840                 {
    1841                     if (errno != 0)
    1842                     {
    1843                         std::stringstream str;
    1844                         str << "Unable to retrieve the current path" << ". Reason: " << strerror(errno) << " [" << errno << "]";
    1845                         Error(str);
    1846                     }
    1847                 }
    1848                 actualTargetDir = currentPath;
    1849         }
    1850         else
    1851         {
    1852                 actualTargetDir = fRunFileName;
    1853         }               
    1854         NotifyOpenedFile(actualTargetDir + '/' + sRun.str(), 3, fOpenedRunFiles);
    1855        
    1856         fOpenedRunFits.clear();
    1857 
    1858         return kSM_Logging;
     1783    if (fDebugIsOn)
     1784    {
     1785        Debug("Starting Run Logging...");   
     1786    }
     1787    //attempt to open run file with current parameters
     1788//    if (fRunNumber == -1)
     1789//        return kSM_BadRunConfig;
     1790    stringstream sRun;
     1791    sRun << fRunNumber;
     1792    fFullRunLogFileName = fRunFileName + '/' + sRun.str() + ".log";
     1793    fRunLogFile.open(fFullRunLogFileName.c_str(), ios_base::out | ios_base::app); //maybe should be app instead of ate
     1794    if (errno != 0)
     1795    {
     1796        stringstream str;
     1797        str << "Unable to open run Log " << fFullRunLogFileName << ". Reason: " << strerror(errno) << " [" << errno << "]";
     1798        Error(str);   
     1799    }
     1800    fFullRunReportFileName = fRunFileName + '/' + sRun.str() + ".rep";
     1801    fRunReportFile.open(fFullRunReportFileName.c_str(), ios_base::out | ios_base::app);
     1802    if (errno != 0)
     1803    {
     1804        stringstream str;
     1805        str << "Unable to open run report " << fFullRunReportFileName << ". Reason: " << strerror(errno) << " [" << errno << "]";
     1806        Error(str);   
     1807    }
     1808   
     1809    if (!fRunLogFile.is_open() || !fRunReportFile.is_open())
     1810    {
     1811        stringstream str;
     1812        str << "Something went wrong while openning nightly files " << fFullRunLogFileName << " and " << fFullRunReportFileName;
     1813        Error(str.str());
     1814        return kSM_BadRunConfig;
     1815    }
     1816    //get the size of the newly opened file.
     1817    struct stat st;
     1818    fBaseSizeRun = 0;
     1819    if (fFileSizesMap.find(fFullRunLogFileName) == fFileSizesMap.end())
     1820    {
     1821        stat(fFullRunLogFileName.c_str(), &st);
     1822        if (errno != 0)
     1823        {
     1824            stringstream str;
     1825            str << "Unable to stat " << fFullRunLogFileName << ". Reason: " << strerror(errno) << " [" << errno << "]";
     1826            Error(str);   
     1827        }
     1828        else
     1829            fBaseSizeRun += st.st_size;
     1830        fFileSizesMap[fFullRunLogFileName] = 0;
     1831    }
     1832    if (fFileSizesMap.find(fFullRunReportFileName) == fFileSizesMap.end())
     1833    {
     1834        stat(fFullRunReportFileName.c_str(), &st);
     1835        if (errno != 0)
     1836        {
     1837            stringstream str;
     1838            str << "Unable to stat " << fFullRunReportFileName << ". Reason: " << strerror(errno) << " [" << errno << "]";
     1839            Error(str);   
     1840        }
     1841        else
     1842            fBaseSizeRun += st.st_size;
     1843        fFileSizesMap[fFullRunReportFileName] = 0;
     1844    }
     1845    string actualTargetDir;
     1846    if (fRunFileName == ".")
     1847    {
     1848        char currentPath[FILENAME_MAX];
     1849        if (!getcwd(currentPath, sizeof(currentPath)))
     1850        {
     1851            if (errno != 0)
     1852            {
     1853                stringstream str;
     1854                str << "Unable to retrieve the current path" << ". Reason: " << strerror(errno) << " [" << errno << "]";
     1855                Error(str);
     1856            }
     1857        }
     1858        actualTargetDir = currentPath;
     1859    }
     1860    else
     1861    {
     1862        actualTargetDir = fRunFileName;   
     1863    }       
     1864    NotifyOpenedFile(actualTargetDir + '/' + sRun.str(), 3, fOpenedRunFiles);
     1865   
     1866    fOpenedRunFits.clear();
     1867
     1868    return kSM_Logging;
    18591869}
    18601870#ifdef HAVE_FITS
    18611871void DataLogger::CreateFitsGrouping(bool runGroup)
    18621872{
    1863     //create the FITS group corresponding to the ending run.ETIENNEICI
     1873    if (fDebugIsOn)
     1874    {
     1875        stringstream str;
     1876        str << "Creating fits group for ";
     1877        if (runGroup)
     1878            str << "run files";
     1879        else
     1880            str << "nightly files";
     1881        Debug(str.str());
     1882    }
     1883    //create the FITS group corresponding to the ending run.
    18641884    CCfits::FITS* groupFile;
    1865 
    1866 #ifdef ONE_RUN_FITS_ONLY
    1867     if (runGroup)
    1868         return;
    1869 #endif
    1870     map<string, string>& filesToGroup = runGroup? fOpenedRunFits : fOpenedNightlyFits;
    1871     unsigned int numFilesToGroup = filesToGroup.size();
     1885    map<string, vector<string> >& filesToGroup = runGroup? fOpenedRunFits : fOpenedNightlyFits;
     1886    unsigned int numFilesToGroup = 0;
     1887    for (map<string, vector<string> >::iterator it=filesToGroup.begin(); it != filesToGroup.end(); it++)
     1888    {
     1889        numFilesToGroup += it->second.size();
     1890    }
     1891    if (fDebugIsOn)
     1892    {
     1893        stringstream str;
     1894        str << "There are " << numFilesToGroup << " tables to group";
     1895        Debug(str.str());
     1896    }
    18721897    if (numFilesToGroup <= 1)
    18731898    {
     
    18831908    {
    18841909        Time time;
    1885         std::stringstream sTime;
     1910        stringstream sTime;
    18861911        sTime << time.Y() << "_" << time.M() << "_" << time.D();
    18871912
    18881913        groupName << fNightlyFileName << '/' << sTime.str() << ".fits";
    18891914    }
     1915    CCfits::Table* groupTable;
     1916    int maxCharLength = 50;//FILENAME_MAX;
    18901917    try
    18911918    {
    18921919        groupFile = new CCfits::FITS(groupName.str(), CCfits::RWmode::Write);
    18931920        //setup the column names
    1894         int maxCharLength = FILENAME_MAX;
    18951921        stringstream pathTypeName;
    18961922        pathTypeName << maxCharLength << "A";
     
    19051931        names.push_back("MEMBER_NAME");
    19061932        dataTypes.push_back(pathTypeName.str());
    1907         CCfits::Table* groupTable = groupFile->addTable("GROUPING", numFilesToGroup, names, dataTypes);
     1933
     1934        groupTable = groupFile->addTable("GROUPING", numFilesToGroup, names, dataTypes);
    19081935     }
    19091936     catch (CCfits::FitsError e)
    19101937     {
    1911          std::stringstream str;
     1938         stringstream str;
    19121939         str << "Could not open or create FITS table GROUPING in  file " << groupName.str() << " reason: " << e.message();
    19131940         Error(str);
     
    19201947    //create appropriate buffer.
    19211948    unsigned char* fitsBuffer = new unsigned char[8 + 3 + 2*maxCharLength + 1]; //+1 for trailling character
     1949    memset(fitsBuffer, 0, 8 + 3 + 2*maxCharLength + 1);
    19221950    char* startOfExtension = reinterpret_cast<char*>(fitsBuffer);
    19231951    char* startOfURI = reinterpret_cast<char*>(&fitsBuffer[8]);
    19241952    char* startOfLocation = reinterpret_cast<char*>(&fitsBuffer[8 + 3]);
    19251953    char* startOfName = reinterpret_cast<char*>(&fitsBuffer[8+3+maxCharLength]);
     1954 //   char* startOfNameVisible = reinterpret_cast<char*>(&fitsBuffer[8 + 3 + 2*maxCharLength]);
    19261955    sprintf(startOfExtension, "%s", "BINTABLE");
    19271956    sprintf(startOfURI, "%s", "URL");
    19281957    int i=1;
    1929     for (map<string, string>::iterator it=filesToGroup.begin(); it!=filesToGroup.end(); it++, i++)
    1930     {
    1931         strcpy(startOfLocation, it->first.c_str());
    1932         strcpy(startOfName, it->second.c_str());
    1933         int status = 0;
    1934         fits_write_tblbytes(groupFile->fitsPointer(), i, 1, 8+3+2*maxCharLength, fitsBuffer, &status);
    1935         if (status)
    1936         {
    1937             stringstream str;
    1938             str << "Could not write row #" << i << "In the fits grouping file " << groupName << ". Cfitsio error code: " << status;
    1939             Error(str.str());
    1940         }
    1941     }
     1958    for (map<string, vector<string> >::iterator it=filesToGroup.begin(); it!=filesToGroup.end(); it++)
     1959        for (vector<string>::iterator jt=it->second.begin(); jt != it->second.end(); jt++, i++)
     1960        {
     1961            strcpy(startOfLocation, it->first.c_str());
     1962            strcpy(startOfName, jt->c_str());
     1963            if (fDebugIsOn)
     1964            {
     1965                stringstream str;
     1966                str << "Grouping " << it->first << " " << *jt;
     1967                Debug(str.str());
     1968            }
     1969 //           strcpy(startOfNameVisible, jt->c_str());
     1970            int status = 0;
     1971            fits_write_tblbytes(groupFile->fitsPointer(), i, 1, 8+3+2*maxCharLength, fitsBuffer, &status);
     1972            if (status)
     1973            {
     1974                stringstream str;
     1975                str << "Could not write row #" << i << "In the fits grouping file " << groupName << ". Cfitsio error code: " << status;
     1976                Error(str.str());
     1977            }
     1978        }
    19421979
    19431980    filesToGroup.clear();
     
    19501987//! Attempts to close the run file.
    19511988//! @returns
    1952 //!             kSM_WaitingRun if success, kSM_FatalError otherwise
     1989//!        kSM_WaitingRun if success, kSM_FatalError otherwise
    19531990int DataLogger::StopRunPlease()
    19541991{
    19551992
    1956         if (fDebugIsOn)
    1957         {
    1958                 Debug("Stopping Run Logging...");       
    1959         }
    1960         if (!fRunLogFile.is_open() || !fRunReportFile.is_open())
    1961                 return kSM_FatalError;
    1962         if (fRunLogFile.is_open())
    1963                 fRunLogFile.close();
    1964         if (fRunReportFile.is_open())
    1965                 fRunReportFile.close();
     1993    if (fDebugIsOn)
     1994    {
     1995        Debug("Stopping Run Logging...");   
     1996    }
     1997    if (!fRunLogFile.is_open() || !fRunReportFile.is_open())
     1998        return kSM_FatalError;
     1999    if (fRunLogFile.is_open())
     2000        fRunLogFile.close();
     2001    if (fRunReportFile.is_open())
     2002        fRunReportFile.close();
    19662003#ifdef HAVE_FITS
    1967         for (SubscriptionsListType::iterator i = fServiceSubscriptions.begin(); i != fServiceSubscriptions.end(); i++)
    1968                 for (std::map<std::string, SubscriptionType>::iterator j = i->second.begin(); j != i->second.end(); j++)
    1969                 {
    1970                                 if (j->second.runFile.IsOpen())
    1971                                         j->second.runFile.Close();     
    1972                 }
    1973 #ifdef ONE_RUN_FITS_ONLY
    1974         if (fRunFitsFile != NULL)
    1975         {
    1976                 delete fRunFitsFile;
    1977                 fRunFitsFile = NULL;   
    1978                 (fNumSubAndFitsData.numOpenFits)--;
    1979         }
     2004    for (SubscriptionsListType::iterator i = fServiceSubscriptions.begin(); i != fServiceSubscriptions.end(); i++)
     2005        for (map<string, SubscriptionType>::iterator j = i->second.begin(); j != i->second.end(); j++)
     2006        {
     2007            if (j->second.runFile.IsOpen())
     2008                j->second.runFile.Close();
     2009        }
     2010    if (fRunFitsFile != NULL)
     2011    {
     2012        delete fRunFitsFile;
     2013        fRunFitsFile = NULL;   
     2014        (fNumSubAndFitsData.numOpenFits)--;
     2015    }
    19802016#endif
    1981 #endif
    1982         NotifyOpenedFile("", 0, fOpenedRunFiles);
    1983         if (fNumSubAndFitsIsOn)
    1984                 fNumSubAndFits->updateService();
    1985 
    1986         CreateFitsGrouping(true);
    1987 
    1988         return kSM_WaitingRun;
     2017    NotifyOpenedFile("", 0, fOpenedRunFiles);
     2018    if (fNumSubAndFitsIsOn)
     2019        fNumSubAndFits->updateService();
     2020
     2021    CreateFitsGrouping(true);
     2022
     2023    return kSM_WaitingRun;
    19892024
    19902025}
     
    19942029//! Attempts to close any openned file.
    19952030//! @returns
    1996 //!     kSM_Ready
     2031//!     kSM_Ready
    19972032int DataLogger::GoToReadyPlease()
    19982033{
    1999         if (fDebugIsOn)
    2000         {
    2001                 Debug("Going to the Ready state...");
    2002         }       
    2003         if (fNightlyLogFile.is_open())
    2004                 fNightlyLogFile.close();
    2005         if (fNightlyReportFile.is_open())
    2006                 fNightlyReportFile.close();
    2007 
    2008         if (fRunLogFile.is_open())
    2009                 fRunLogFile.close();
    2010         if (fRunReportFile.is_open())
    2011                 fRunReportFile.close();
    2012                
     2034    if (fDebugIsOn)
     2035    {
     2036        Debug("Going to the Ready state...");
     2037    }   
     2038    if (fNightlyLogFile.is_open())
     2039        fNightlyLogFile.close();
     2040    if (fNightlyReportFile.is_open())
     2041        fNightlyReportFile.close();
     2042
     2043    if (fRunLogFile.is_open())
     2044        fRunLogFile.close();
     2045    if (fRunReportFile.is_open())
     2046        fRunReportFile.close();
     2047       
    20132048#ifdef HAVE_FITS
    2014         for (SubscriptionsListType::iterator i = fServiceSubscriptions.begin(); i != fServiceSubscriptions.end(); i++)
    2015                 for (std::map<std::string, SubscriptionType>::iterator j = i->second.begin(); j != i->second.end(); j++)
    2016                 {
    2017                                 if (j->second.nightlyFile.IsOpen())
    2018                                         j->second.nightlyFile.Close();
    2019                                 if (j->second.runFile.IsOpen())
    2020                                         j->second.runFile.Close();     
    2021                 }
    2022 #ifdef ONE_RUN_FITS_ONLY
    2023         if (fRunFitsFile != NULL)
    2024         {
    2025                 delete fRunFitsFile;
    2026                 fRunFitsFile = NULL;
    2027                 (fNumSubAndFitsData.numOpenFits)--;
    2028         }
     2049    for (SubscriptionsListType::iterator i = fServiceSubscriptions.begin(); i != fServiceSubscriptions.end(); i++)
     2050        for (map<string, SubscriptionType>::iterator j = i->second.begin(); j != i->second.end(); j++)
     2051        {
     2052            if (j->second.nightlyFile.IsOpen())
     2053                j->second.nightlyFile.Close();
     2054            if (j->second.runFile.IsOpen())
     2055                j->second.runFile.Close();
     2056        }
     2057    if (fRunFitsFile != NULL)
     2058    {
     2059        delete fRunFitsFile;
     2060        fRunFitsFile = NULL;
     2061        (fNumSubAndFitsData.numOpenFits)--;
     2062    }
    20292063#endif
    2030 #endif
    2031         if (GetCurrentState() == kSM_Logging)
    2032                 NotifyOpenedFile("", 0, fOpenedRunFiles);
    2033         if (GetCurrentState() == kSM_Logging ||
    2034             GetCurrentState() == kSM_WaitingRun ||
    2035             GetCurrentState() == kSM_NightlyOpen)
    2036         {
    2037                 NotifyOpenedFile("", 0, fOpenedNightlyFiles);
    2038                 if (fNumSubAndFitsIsOn)
    2039                         fNumSubAndFits->updateService();
    2040         }
    2041         CreateFitsGrouping(true);
    2042         CreateFitsGrouping(false);
    2043 
    2044         return kSM_Ready;
     2064    if (GetCurrentState() == kSM_Logging)
     2065        NotifyOpenedFile("", 0, fOpenedRunFiles);
     2066    if (GetCurrentState() == kSM_Logging ||
     2067        GetCurrentState() == kSM_WaitingRun ||
     2068        GetCurrentState() == kSM_NightlyOpen)
     2069    {
     2070        NotifyOpenedFile("", 0, fOpenedNightlyFiles);
     2071        if (fNumSubAndFitsIsOn)
     2072            fNumSubAndFits->updateService();
     2073    }
     2074    CreateFitsGrouping(true);
     2075    CreateFitsGrouping(false);
     2076
     2077    return kSM_Ready;
    20452078}
    20462079// --------------------------------------------------------------------------
     
    20482081//! Implements the transition towards kSM_WaitingRun
    20492082//! Does nothing really.
    2050 //!     @returns
    2051 //!             kSM_WaitingRun
     2083//!    @returns
     2084//!        kSM_WaitingRun
    20522085int DataLogger::NightlyToWaitRunPlease()
    20532086{
    2054         if (fDebugIsOn)
    2055         {
    2056                 Debug("Going to Wait Run Number state...");     
    2057         }
    2058         return kSM_WaitingRun; 
     2087    if (fDebugIsOn)
     2088    {
     2089        Debug("Going to Wait Run Number state...");   
     2090    }
     2091    return kSM_WaitingRun;   
    20592092}
    20602093
     
    20632096    fDebugIsOn = conf.Get<bool>("debug");
    20642097
    2065         //Set the block or allow list
    2066         fBlackList.clear();
    2067         fWhiteList.clear();
     2098    //Set the block or allow list
     2099    fBlackList.clear();
     2100    fWhiteList.clear();
    20682101    if (conf.Has("block"))
    20692102    {
    2070         vector<string> vec = conf.Get<vector<string>>("block");
    2071         if (vec.size() != 0)
    2072         {
    2073                 fHasBlackList = true;
    2074                 if (fDebugIsOn)
    2075                                 Debug("Setting BLOCK list:");
    2076         }
    2077         for (vector<string>::iterator it = vec.begin(); it != vec.end(); it++)
    2078         {
    2079             fBlackList.insert(*it);
    2080             if (fDebugIsOn)
    2081                 Debug("                   " + *it);
    2082         }
     2103        vector<string> vec = conf.Get<vector<string>>("block");
     2104        if (vec.size() != 0)
     2105        {
     2106            fHasBlackList = true;
     2107            if (fDebugIsOn)
     2108                Debug("Setting BLOCK list:");
     2109        }
     2110        for (vector<string>::iterator it = vec.begin(); it != vec.end(); it++)
     2111        {
     2112            fBlackList.insert(*it);
     2113            if (fDebugIsOn)
     2114                Debug("                   " + *it);
     2115        }
    20832116    }
    20842117    if (conf.Has("allow"))
    20852118    {
    2086         vector<string> vec = conf.Get<vector<string>>("allow");
    2087         if (vec.size() != 0)
    2088         {
    2089                 fHasWhiteList = true;
    2090                 if (fDebugIsOn)
    2091                         Debug("Setting ALLOW list:");
    2092         }
    2093         for (vector<string>::iterator it=vec.begin(); it != vec.end(); it++)
    2094         {
    2095                 fWhiteList.insert(*it);
    2096                 if (fDebugIsOn)
    2097                         Debug("                   " + *it);
    2098         }
     2119        vector<string> vec = conf.Get<vector<string>>("allow");
     2120        if (vec.size() != 0)
     2121        {
     2122            fHasWhiteList = true;
     2123            if (fDebugIsOn)
     2124                Debug("Setting ALLOW list:");
     2125        }
     2126        for (vector<string>::iterator it=vec.begin(); it != vec.end(); it++)
     2127        {
     2128            fWhiteList.insert(*it);
     2129            if (fDebugIsOn)
     2130                Debug("                   " + *it);
     2131        }
     2132    }
     2133    //Set the grouping
     2134    if (conf.Has("group"))
     2135    {
     2136        vector<string> vec = conf.Get<vector<string>>("group");
     2137        if (vec.size() != 0)
     2138            if (fDebugIsOn)
     2139                Debug("Setting GROUPING list:");
     2140        for (vector<string>::iterator it=vec.begin(); it != vec.end(); it++)
     2141        {
     2142            fGrouping.insert(*it);
     2143            if (fDebugIsOn)
     2144                Debug("                   " + *it);
     2145        }
    20992146    }
    21002147    return true;
     
    21092156    //log.SetWindow(stdscr);
    21102157    if (conf.Has("log"))
    2111         if (!wout.OpenLogFile(conf.Get<std::string>("log")))
    2112             wout << kRed << "ERROR - Couldn't open log-file " << conf.Get<std::string>("log") << ": " << strerror(errno) << std::endl;
     2158        if (!wout.OpenLogFile(conf.Get<string>("log")))
     2159            wout << kRed << "ERROR - Couldn't open log-file " << conf.Get<string>("log") << ": " << strerror(errno) << endl;
    21132160
    21142161    // Start io_service.Run to use the StateMachineImp::Run() loop
     
    21252172void RunThread(DataLogger* logger)
    21262173{
    2127         // This is necessary so that the StateMachine Thread can signal the
    2128         // Readline thread to exit
    2129         logger->Run(true);
    2130         Readline::Stop();       
     2174    // This is necessary so that the StateMachine Thread can signal the
     2175    // Readline thread to exit
     2176    logger->Run(true);
     2177    Readline::Stop();   
    21312178}
    21322179
     
    21402187
    21412188    if (conf.Has("log"))
    2142         if (!wout.OpenLogFile(conf.Get<std::string>("log")))
    2143             win << kRed << "ERROR - Couldn't open log-file " << conf.Get<std::string>("log") << ": " << strerror(errno) << std::endl;
     2189        if (!wout.OpenLogFile(conf.Get<string>("log")))
     2190            win << kRed << "ERROR - Couldn't open log-file " << conf.Get<string>("log") << ": " << strerror(errno) << endl;
    21442191
    21452192    DataLogger logger(wout);
     
    21492196    shell.SetReceiver(logger);
    21502197
    2151         boost::thread t(boost::bind(RunThread, &logger));
    2152        
    2153         shell.Run(); // Run the shell
    2154        
    2155         logger.Stop();
    2156        
    2157         //Wait until the StateMachine has finished its thread
    2158         //before returning and destroyinng the dim objects which might
    2159         //still be in use.
    2160         t.join();
     2198    boost::thread t(boost::bind(RunThread, &logger));
     2199   
     2200    shell.Run(); // Run the shell
     2201   
     2202    logger.Stop();
     2203   
     2204    //Wait until the StateMachine has finished its thread
     2205    //before returning and destroyinng the dim objects which might
     2206    //still be in use.
     2207    t.join();
    21612208
    21622209    return 0;
     
    22352282    po::options_description configs("Scheduler options");
    22362283    configs.add_options()
    2237         ("block,b",   vars<string>(), "Black-list of services")
    2238         ("allow,a",   vars<string>(), "White-list of services")
    2239         ("debug",     po_bool(),      "Debug mode. Print clear text of received service reports to log-stream")
     2284        ("block,b", vars<string>(), "Black-list of services")
     2285        ("allow,a", vars<string>(), "White-list of services")
     2286        ("debug",   po_bool(),      "Debug mode. Print clear text of received service reports to log-stream")
     2287        ("group,g", vars<string>(), "Grouping of services into a single run-Fits")
    22402288        ;
    22412289
     
    22572305        vm = conf.Parse(argc, argv);
    22582306    }
    2259     catch (std::exception &e)
     2307    catch (exception &e)
    22602308    {
    22612309#if BOOST_VERSION > 104000
     
    23002348            return RunShell<LocalConsole>(conf);
    23012349    }
    2302 /*    catch (std::exception& e)
     2350/*    catch (exception& e)
    23032351    {
    23042352        cerr << "Exception: " << e.what() << endl;
Note: See TracChangeset for help on using the changeset viewer.