Changeset 10264 for trunk


Ignore:
Timestamp:
03/30/11 10:56:42 (14 years ago)
Author:
lyard
Message:
 
File:
1 edited

Legend:

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

    r10183 r10264  
    1 
     1//****************************************************************
     2/** @class DataLogger
     3 
     4  @brief Logs all message and infos between the services
     5 
     6  This is the main logging class facility.
     7  It derives from StateMachineDim and DimInfoHandler. the first parent is here to enforce
     8  a state machine behaviour, while the second one is meant to make the dataLogger receive
     9  dim services to which it subscribed from.
     10  The possible states and transitions of the machine are:
     11  \dot
     12  digraph datalogger {
     13                node [shape=record, fontname=Helvetica, fontsize=10];
     14        e [label="Error" color="red"];
     15   r [label="Ready"]
     16   d [label="DailyOpen"]
     17   w [label="WaitingRun"]
     18        l [label="Logging"]
     19   b [label="BadDailyconfig" color="red"]
     20   c [label="BadRunConfig" color="red"]
     21 
     22  e -> r
     23  r -> e
     24  r -> d
     25  r -> b
     26  d -> w
     27  d -> r
     28  w -> r
     29  l -> r
     30  l -> w
     31  b -> d
     32  w -> c
     33  w -> l
     34  b -> r
     35  c -> r
     36  c -> l
     37  }
     38  \enddot
     39 
     40  @todo
     41        - Retrieve also the messages, not only the infos
     42 */
     43 //****************************************************************
    244#include "Event.h"
    345#include "Time.h"
    446#include "StateMachineDim.h"
    547#include "ServiceList.h"
     48#include "Converter.h"
     49#include "MessageImp.h"
     50
    651#include <fstream>
    752
    853#include <boost/bind.hpp>
    954
    10 //****************************************************************
    11 /** @class DataLogger
    12  *
    13  * @brief Logs all message and infos between the services
    14  *
    15  * This is the main logging class facility.
    16  * It derives from StateMachineDim and DimInfoHandler. the first parent is here to enforce
    17  * a state machine behaviour, while the second one is meant to make the dataLogger receive
    18  * dim services to which it subscribed from.
    19  * The possible states and transitions of the machine are:
    20  * \dot
    21  * digraph datalogger {
    22  *              node [shape=record, fontname=Helvetica, fontsize=10];
    23  *      e [label="Error" color="red"];
    24  *  r [label="Ready"]
    25  *  d [label="DailyOpen"]
    26  *  w [label="WaitingRun"]
    27  *      l [label="Logging"]
    28  *  b [label="BadDailyconfig" color="red"]
    29  *  c [label="BadRunConfig" color="red"]
    30  *
    31  * e -> r
    32  * r -> e
    33  * r -> d
    34  * r -> b
    35  * d -> w
    36  * d -> r
    37  * w -> r
    38  * l -> r
    39  * l -> w
    40  * b -> d
    41  * w -> c
    42  * w -> l
    43  * b -> r
    44  * c -> r
    45  * c -> l
    46  * }
    47  * \enddot
    48  *
    49  * @todo
    50  *      - A lot
    51  ****************************************************************/
     55#include <astroroot.h>
     56
    5257class DataLogger : public StateMachineDim, DimInfoHandler
    5358{
     
    6873private:
    6974        //Define all the data structure specific to the DataLogger here
    70         std::ofstream fDailyFile; /// ofstream for the dailyfile
    71         std::ofstream fRunFile; /// ofstream for the run-specific file
    72         std::string fDailyFileName; /// base path of the dailyfile
    73         std::string fRunFileName; ///base path of the run file
    74         int runNumber; ///run number (-1 means no run number specified)
     75        /// ofstream for the dailyLogfile
     76        std::ofstream fDailyLogFile;
     77        /// ofstream for the run-specific Log file
     78        std::ofstream fRunLogFile;
     79
     80        /// ofstream for the daily report file
     81        std::ofstream fDailyReportFile;
     82        /// ofstream for the run-specific report file
     83        std::ofstream fRunReportFile;
     84        /// base path of the dailyfile
     85        std::string fDailyFileName;
     86        ///base path of the run file
     87        std::string fRunFileName;
     88        ///run number (-1 means no run number specified)
     89        int fRunNumber;
     90        ///Current year
     91        short fYear;
     92        ///Current Month
     93        short fMonth;
     94        ///Current Day
     95        short fDay;
     96        ///Current Hour
     97        short fHour;
     98        ///Current Minute
     99        short fMin;
     100        ///Current Second
     101        short fSec;
     102        ///Current Milliseconds
     103        int fMs;
     104        ///Current Service Quality
     105        int fQuality;
     106        ///Modified Julian Date
     107        double fMjD;
    75108       
    76109        ///Define all the static names
    77         static const char* configDay;
    78         static const char* configRun;
    79         static const char* configRunNumber;
    80         static const char* configLog;
    81         static const char* transStart;
    82         static const char* transStop;
    83         static const char* transStartRun;
    84         static const char* transStopRun;
    85         static const char* transReset;
    86         static const char* transWait;
    87         static const char* runNumberInfo; ///< This is the name of the dimInfo received to specify the run number. It must be updated once the final name will be defined
    88        
    89         int Execute(); ///Inherited from state machine impl
    90        
    91         int Transition(const Event& evt); ///Inherited from state machine impl
    92        
    93         int Configure(const Event& evt); ///Inherited from state machine impl
     110        static const char* fConfigDay;
     111        static const char* fConfigRun;
     112        static const char* fConfigRunNumber;
     113        static const char* fConfigLog;
     114        static const char* fTransStart;
     115        static const char* fTransStop;
     116        static const char* fTransStartRun;
     117        static const char* fTransStopRun;
     118        static const char* fTransReset;
     119        static const char* fTransWait;
     120        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
     121        ///Inherited from state machine impl
     122        int Execute();
     123       
     124        ///Inherited from state machine impl
     125        int Transition(const Event& evt);
     126       
     127        ///Inherited from state machine impl
     128        int Configure(const Event& evt);
    94129       
    95130        //overloading of DIM's infoHandler function
    96         void infoHandler(); ///Inherited from DimInfoHandler
    97        
    98         ServiceList fServiceList;///for obtaining the name of the existing services
    99        
    100         std::map<std::string, std::vector<DimStampedInfo> > fServiceSubscriptions; ///All the services to which we've subscribed to. Sorted by server name
    101        
    102         //internal methods
    103         void LogPlease(DimInfo* I); ///Logging method for the services info received
    104         std::string ToString(const char *format, const void *data, int size); ///Convertion from raw format to human-readable string
    105         //configure methods
    106         int ConfigureDailyFileName(const Event& evt); ///Configuration of the daily file path
    107         int ConfigureRunFileName(const Event& evt); ///Configuration fo the file name
    108         //TODO this will be given by an info, not a command.
    109         int ConfigureRunNumber(const Event& evt); ///DEPREC - configuration of the run number
    110         int LogMessagePlease(const Event& evt); ///logging method for the messages
    111         void CheckForServicesUpdate(); ///checks with fServiceList whether or not the services got updated
    112         void CheckForRunNumber(DimInfo* I); ///checks whether or not the current info being treated is a run number
    113         //transitions methods
    114         int StartPlease(); /// start transition
    115         int StopPlease(); ///stop transition
    116         int StartRunPlease(); ///from waiting to logging transition
    117         int StopRunPlease(); /// from logging to waiting transition
    118         int ResetPlease(); ///reset transition
    119         int DailyToWaitRunPlease(); ///from dailyOpen to waiting transition
    120 
    121         void InitServiceSubscription(); ///first subscription to the dim services.
    122        
    123 
     131        void infoHandler();
     132       
     133        ///for obtaining the name of the existing services
     134        ServiceList fServiceList;
     135       
     136       
     137        ///A std pair to store both the DimInfo name and the actual DimInfo pointer
     138//      typedef std::pair<std::string, DimStampedInfo*> subscriptionType;
     139        ///All the services to which we've subscribed to. Sorted by server name
     140//      std::map<const std::string, std::vector<subscriptionType > > fServiceSubscriptions;
     141
     142        ///A std pair to store both the DimInfo pointer and the corresponding outputted fits file
     143        struct SubscriptionType
     144        {
     145                ///daily FITS output file
     146                AstroRootIo     dailyFile;
     147                ///run-specific FITS output file
     148                AstroRootIo     runFile;
     149                ///the actual dimInfo pointer
     150                DimStampedInfo* dimInfo;
     151                ///the number of existing handlers to this structure.
     152                ///This is required otherwise I MUST handle the deleting of dimInfo outside from the destructor
     153                int* numCopies;
     154                void operator = (const SubscriptionType& other)
     155                {
     156                        dailyFile = other.dailyFile;
     157                        runFile = other.runFile;
     158                        dimInfo = other.dimInfo;       
     159                        numCopies = other.numCopies;
     160                        (*numCopies)++;
     161                }
     162                SubscriptionType(const SubscriptionType& other)
     163                {
     164                        dailyFile = other.dailyFile;
     165                        runFile = other.runFile;
     166                        dimInfo = other.dimInfo;
     167                        numCopies = other.numCopies;
     168                        (*numCopies)++;
     169                }
     170                SubscriptionType(DimStampedInfo* info)
     171                {
     172                        dimInfo = info;
     173                        numCopies = new int(1);
     174                }
     175                SubscriptionType()
     176                {
     177                        dimInfo = NULL;
     178                        numCopies = new int(1);
     179                }
     180                ~SubscriptionType()
     181                {
     182                        if (numCopies)
     183                        (*numCopies)--;
     184                        if (numCopies)
     185                        if (*numCopies < 1)
     186                        {
     187                                if (dailyFile.IsOpen())
     188                                        dailyFile.Close();
     189                                if (runFile.IsOpen())
     190                                        runFile.Close();
     191                                if (dimInfo)
     192                                delete dimInfo;
     193                                if (numCopies) 
     194                                delete numCopies;
     195                                dimInfo = NULL;
     196                                numCopies = NULL;
     197                        }
     198                }
     199        };
     200        typedef std::map<const std::string, std::map<std::string, SubscriptionType>> SubscriptionsListType;
     201        ///All the services to which we have subscribed to, sorted by server name.
     202        SubscriptionsListType fServiceSubscriptions;
     203
     204
     205        ///Reporting method for the services info received
     206        void ReportPlease(DimInfo* I, SubscriptionType& sub); 
     207
     208        ///Configuration of the daily file path
     209        int ConfigureDailyFileName(const Event& evt);
     210        ///Configuration fo the file name
     211        int ConfigureRunFileName(const Event& evt);
     212        ///DEPREC - configuration of the run number
     213        int ConfigureRunNumber(const Event& evt);
     214        ///logging method for the messages
     215        int LogMessagePlease(const Event& evt);
     216        ///checks whether or not the current info being treated is a run number
     217        void CheckForRunNumber(DimInfo* I);
     218
     219        /// start transition
     220        int StartPlease();
     221        ///from waiting to logging transition
     222        int StartRunPlease();
     223        /// from logging to waiting transition
     224        int StopRunPlease();
     225        ///stop and reset transition
     226        int GoToReadyPlease();
     227        ///from dailyOpen to waiting transition
     228        int DailyToWaitRunPlease();
     229        ///Open fits files
     230        void OpenFITSFilesPlease(SubscriptionType& sub);
     231        ///Write data to FITS files
     232        void WriteToFITS(SubscriptionType& sub);
     233        ///Allocate the buffers required for fits
     234        void AllocateFITSBuffers(SubscriptionType& sub);
     235public:
     236        ///checks with fServiceList whether or not the services got updated
     237        void CheckForServicesUpdate();
    124238       
    125239}; //DataLogger
     
    127241//static members initialization
    128242//since I do not check the transition/config names any longer, indeed maybe these could be hard-coded... but who knows what will happen in the future ?
    129 const char* DataLogger::configDay = "CONFIG_DAY";
    130 const char* DataLogger::configRun = "CONFIG_RUN";
    131 const char* DataLogger::configRunNumber = "CONFIG_RUN_NUMBER";
    132 const char* DataLogger::configLog = "LOG";
    133 const char* DataLogger::transStart = "START";
    134 const char* DataLogger::transStop = "STOP";
    135 const char* DataLogger::transStartRun = "START_RUN";
    136 const char* DataLogger::transStopRun = "STOP_RUN";
    137 const char* DataLogger::transReset = "RESET";
    138 const char* DataLogger::transWait = "WAIT_RUN_NUMBER";
    139 const char* DataLogger::runNumberInfo = "RUN_NUMBER";
    140 
    141 /****************************************************************
    142  *
    143  * DATA LOGGER CONSTRUCTOR
    144  *
    145  ****************************************************************/
    146  //! Default constructor
     243const char* DataLogger::fConfigDay = "CONFIG_DAY";
     244const char* DataLogger::fConfigRun = "CONFIG_RUN";
     245const char* DataLogger::fConfigRunNumber = "CONFIG_RUN_NUMBER";
     246const char* DataLogger::fConfigLog = "LOG";
     247const char* DataLogger::fTransStart = "START";
     248const char* DataLogger::fTransStop = "STOP";
     249const char* DataLogger::fTransStartRun = "START_RUN";
     250const char* DataLogger::fTransStopRun = "STOP_RUN";
     251const char* DataLogger::fTransReset = "RESET";
     252const char* DataLogger::fTransWait = "WAIT_RUN_NUMBER";
     253const char* DataLogger::fRunNumberInfo = "RUN_NUMBER";
     254
     255// --------------------------------------------------------------------------
     256//
     257//! Default constructor. The name of the machine is given DATA_LOGGER
     258//! and the state is set to kSM_Ready at the end of the function.
     259//
     260//!Setup the allows states, configs and transitions for the data logger
     261//
    147262DataLogger::DataLogger() : StateMachineDim(std::cout, "DATA_LOGGER")
    148263{
    149264                //initialize member data
    150                 fDailyFileName = "";
    151                 fRunFileName = "";
    152                 runNumber = -1;
     265                fDailyFileName = "/home/lyard/log";
     266                fRunFileName = "/home/lyard/log";
     267                fRunNumber = 12345;
    153268                //Give a name to this machine's specific states
    154269                AddStateName(kSM_DailyOpen, "Daily_File_Openened");
     
    159274
    160275                /*Add the possible transitions for this machine*/
    161                 AddTransition(kSM_DailyOpen, transStart, kSM_Ready, kSM_BadDailyConfig) //start the daily logging. daily file location must be specified already
     276                AddTransition(kSM_DailyOpen, fTransStart, kSM_Ready, kSM_BadDailyConfig) //start the daily logging. daily file location must be specified already
    162277                        ->AssignFunction(boost::bind(&DataLogger::StartPlease, this));
    163                 AddTransition(kSM_Ready, transStop, kSM_DailyOpen, kSM_WaitingRun, kSM_Logging) //stop the data logging
    164                         ->AssignFunction(boost::bind(&DataLogger::StopPlease, this));
    165                 AddTransition(kSM_Logging, transStartRun, kSM_WaitingRun, kSM_BadRunConfig) //start the run logging. run file location must be specified already.
     278                AddTransition(kSM_Ready, fTransStop, kSM_DailyOpen, kSM_WaitingRun, kSM_Logging) //stop the data logging
     279                        ->AssignFunction(boost::bind(&DataLogger::GoToReadyPlease, this));
     280                AddTransition(kSM_Logging, fTransStartRun, kSM_WaitingRun, kSM_BadRunConfig) //start the run logging. run file location must be specified already.
    166281                        ->AssignFunction(boost::bind(&DataLogger::StartRunPlease, this));
    167                 AddTransition(kSM_WaitingRun, transStopRun, kSM_Logging)
     282                AddTransition(kSM_WaitingRun, fTransStopRun, kSM_Logging)
    168283                        ->AssignFunction(boost::bind(&DataLogger::StopRunPlease, this));
    169                 AddTransition(kSM_Ready, transReset, kSM_Error, kSM_BadDailyConfig, kSM_BadRunConfig, kSM_Error) //transition to exit error states. dunno if required or not, would close the daily file if already openned.
    170                         ->AssignFunction(boost::bind(&DataLogger::ResetPlease, this));
    171                 AddTransition(kSM_WaitingRun, transWait, kSM_DailyOpen)
     284                AddTransition(kSM_Ready, fTransReset, kSM_Error, kSM_BadDailyConfig, kSM_BadRunConfig, kSM_Error) //transition to exit error states. dunno if required or not, would close the daily file if already openned.
     285                        ->AssignFunction(boost::bind(&DataLogger::GoToReadyPlease, this));
     286                AddTransition(kSM_WaitingRun, fTransWait, kSM_DailyOpen)
    172287                        ->AssignFunction(boost::bind(&DataLogger::DailyToWaitRunPlease, this));
    173288                /*Add the possible configurations for this machine*/
    174                 AddConfiguration(configDay, kSM_Ready, kSM_BadDailyConfig) //configure the daily file location. cannot be done before the file is actually opened
     289                AddConfiguration(fConfigDay, "C", kSM_Ready, kSM_BadDailyConfig) //configure the daily file location. cannot be done before the file is actually opened
    175290                        ->AssignFunction(boost::bind(&DataLogger::ConfigureDailyFileName, this, _1));
    176                 AddConfiguration(configRun, kSM_Ready, kSM_BadDailyConfig, kSM_DailyOpen, kSM_WaitingRun, kSM_BadRunConfig) //configure the run file location. cannot be done before the file is actually opened, and not in a dailly related error.
     291                AddConfiguration(fConfigRun, "C", kSM_Ready, kSM_BadDailyConfig, kSM_DailyOpen, kSM_WaitingRun, kSM_BadRunConfig) //configure the run file location. cannot be done before the file is actually opened, and not in a dailly related error.
    177292                        ->AssignFunction(boost::bind(&DataLogger::ConfigureRunFileName, this, _1));
    178                 /*wait for Dim to finish initializing*/
    179                 /*just a sleep for now. */
    180                 /*TODO: add a better way to wait: poll DIM for something I guess. Maybe get the configuration from conf server ? */
    181 
    182                 usleep(1000000); //10ms
    183293               
    184294                //Provide a logging command
     
    187297                //is already done in StateMachineImp.cc
    188298                //Thus I'll simply add a configuration, which I will treat as the logging command
    189                 AddConfiguration(configRun, kSM_DailyOpen, kSM_Logging, kSM_WaitingRun, kSM_BadRunConfig)
     299                AddConfiguration(fConfigLog, "C", kSM_DailyOpen, kSM_Logging, kSM_WaitingRun, kSM_BadRunConfig)
    190300                        ->AssignFunction(boost::bind(&DataLogger::LogMessagePlease, this, _1));
    191                        
    192                 InitServiceSubscription();
     301               
     302                fServiceList.SetHandler(this);
     303                CheckForServicesUpdate();
    193304
    194305                //All configuration done, callback funtions set, go to ready state and thus prevent the run loop from being executed
    195306                SetReady();
    196307}
    197 //! Initialization of the subscription to the services.
    198 void DataLogger::InitServiceSubscription()
    199 {
    200         //assign myself as the info handler
    201         fServiceList.SetHandler(this);
    202 
    203         //crawl through the list of services and subscribe to all of them
    204         //TODO I still haven't figured out how the update of services shouldbe performed
    205         //TODO: I don't think that the reference would work in this case because what is returned is a temporary. but should try anyway in case this works...
     308// --------------------------------------------------------------------------
     309//
     310//! Checks for changes in the existing services.
     311//! Any new service will be added to the service list, while the ones which disappeared are removed.
     312//! @todo
     313//!     add the configuration (using the conf class ?)
     314//
     315void DataLogger::CheckForServicesUpdate()
     316{
     317
     318        //get the current server list
    206319        const std::vector<std::string> serverList = fServiceList.GetServerList();
    207         for (unsigned int i=0;i<serverList.size();i++)
    208         {//get the service list associated with each server
    209                 if (strstr(serverList[i].c_str(), "DIS_DNS") || strstr(serverList[i].c_str(), "DATA_LOGGER"))
     320        //first let's remove the servers that may have disapeared
     321        //can't treat the erase on maps the same way as for vectors. Do it the safe way instead
     322        std::vector<std::string> toBeDeleted;
     323        for (SubscriptionsListType::iterator cListe = fServiceSubscriptions.begin(); cListe != fServiceSubscriptions.end(); cListe++)
     324        {
     325                std::vector<std::string>::const_iterator givenServers;
     326                for (givenServers=serverList.begin(); givenServers!= serverList.end(); givenServers++)
     327                        if (cListe->first == *givenServers)
     328                                break;
     329                if (givenServers == serverList.end())//server vanished. Remove it
     330                        toBeDeleted.push_back(cListe->first);
     331        }
     332        for (std::vector<std::string>::const_iterator it = toBeDeleted.begin(); it != toBeDeleted.end(); it++)
     333                fServiceSubscriptions.erase(*it);
     334
     335        //now crawl through the list of servers, and see if there was some updates
     336        for (std::vector<std::string>::const_iterator i=serverList.begin(); i!=serverList.end();i++)
     337        {
     338                //skip the two obvious excluded services
     339                if ((i->find("DIS_DNS") != std::string::npos) ||
     340                    (i->find("DATA_LOGGER") != std::string::npos))
    210341                        continue;
    211                 for (std::vector<std::string>::const_iterator j=fServiceList.begin(serverList[i]); j != fServiceList.end(serverList[i]); j++)
    212                 {//and subscribe to each service !
    213                         fServiceSubscriptions[serverList[i]].push_back(DimStampedInfo(j->c_str(), const_cast<char*>(""), this));
    214                 }
    215         }
    216 }
    217 //! destructor
     342                //find the current server in our subscription list     
     343                SubscriptionsListType::iterator cSubs = fServiceSubscriptions.find(*i);
     344                //get the service list of the current server
     345                std::vector<std::string> cServicesList = fServiceList.GetServiceList(*i);
     346                if (cSubs != fServiceSubscriptions.end())//if the current server already is in our subscriptions
     347                {                                                                                //then check and update our list of subscriptions
     348                        //first, remove the services that may have dissapeared.
     349                        std::map<std::string, SubscriptionType>::iterator serverSubs;
     350                        std::vector<std::string>::const_iterator givenSubs;
     351                        toBeDeleted.clear();
     352                        for (serverSubs=cSubs->second.begin(); serverSubs != cSubs->second.end(); serverSubs++)
     353                        {
     354                                for (givenSubs = cServicesList.begin(); givenSubs != cServicesList.end(); givenSubs++)
     355                                        if (serverSubs->first == *givenSubs)
     356                                                break;
     357                                if (givenSubs == cServicesList.end())
     358                                {
     359                                        toBeDeleted.push_back(serverSubs->first);
     360                                }       
     361                        }
     362                        for (std::vector<std::string>::const_iterator it = toBeDeleted.begin(); it != toBeDeleted.end(); it++)
     363                                cSubs->second.erase(*it);
     364                        //now check for new services
     365                        for (givenSubs = cServicesList.begin(); givenSubs != cServicesList.end(); givenSubs++)
     366                        {
     367                                if (*givenSubs == "SERVICE_LIST")
     368                                        continue;
     369                                if (cSubs->second.find(*givenSubs) == cSubs->second.end())
     370                                {//service not found. Add it
     371                                        cSubs->second[*givenSubs].dimInfo = new DimStampedInfo(((*i) + "/" + *givenSubs).c_str(), const_cast<char*>(""), this);
     372                                }       
     373                        }
     374                }
     375                else //server not found in our list. Create its entry
     376                {
     377                        fServiceSubscriptions[*i] = std::map<std::string, SubscriptionType>();
     378                        std::map<std::string, SubscriptionType>& liste = fServiceSubscriptions[*i];
     379                        for (std::vector<std::string>::const_iterator j = cServicesList.begin(); j!= cServicesList.end(); j++)
     380                        {
     381                                if (*j == "SERVICE_LIST")
     382                                        continue;
     383                                liste[*j].dimInfo = new DimStampedInfo(((*i) + "/" + (*j)).c_str(), const_cast<char*>(""), this);
     384                        }
     385                }       
     386        }
     387}
     388// --------------------------------------------------------------------------
     389//
     390//! Destructor
     391//
    218392DataLogger::~DataLogger()
    219393{
    220         if (fDailyFile.is_open())
    221                 fDailyFile.close();
    222         if (fRunFile.is_open())
    223                 fRunFile.close();
    224 ;
    225 }
    226 /****************************************************************
    227  *
    228  * DATA LOGGER'S EXECUTE
    229  *
    230  ****************************************************************/
    231  //! Execute
    232  //! Shouldn't be run as we use callbacks instead
     394        //close the files
     395        if (fDailyLogFile.is_open())
     396                fDailyLogFile.close();
     397        if (fDailyReportFile.is_open())
     398                fDailyReportFile.close();
     399        if (fRunLogFile.is_open())
     400                fRunLogFile.close();
     401        if (fRunReportFile.is_open())
     402                fRunReportFile.close();
     403        //release the services subscriptions
     404        fServiceSubscriptions.clear();
     405}
     406// --------------------------------------------------------------------------
     407//
     408//! Execute
     409//! Shouldn't be run as we use callbacks instead
     410//
    233411int DataLogger::Execute()
    234412{
     
    246424        case kSM_BadRunConfig:
    247425                return GetCurrentState();
    248        
    249426        }
    250427        //this line below should never be hit. It here mainly to remove warnings at compilation
    251428        return kSM_FatalError;
    252429}
    253 /****************************************************************
    254  *
    255  * DATA LOGGER'S TRANSITION
    256  *
    257  ****************************************************************/
    258 
    259  //! Shouldn't be run as we use callbacks instead
     430// --------------------------------------------------------------------------
     431//
     432//! Shouldn't be run as we use callbacks instead
     433//
    260434 int DataLogger::Transition(const Event& evt)
    261435{
     
    273447                                case kSM_BadRunConfig:
    274448                                case kSM_Error:
    275                                         return ResetPlease();
     449                                        return GoToReadyPlease();
    276450                                       
    277451                                case kSM_Logging:
    278452                                case kSM_WaitingRun:
    279453                                case kSM_DailyOpen:
    280                                         return StopPlease();
     454                                        return GoToReadyPlease();
    281455                        }
    282456                break;
     
    319493        return kSM_FatalError;
    320494}
    321 /****************************************************************
    322  *
    323  * DATA LOGGER'S CONFIGURE
    324  *
    325  ****************************************************************/
     495// --------------------------------------------------------------------------
     496//
    326497//! Shouldn't be run as we use callbacks instead
     498//
    327499 int DataLogger::Configure(const Event& evt)
    328500{
     
    344516                case kSM_Logging:
    345517                case kSM_DailyOpen:
    346                                 return LogMessagePlease(evt);   
     518//TODO check that this is indeed correct
     519                                return 0;//LogMessagePlease(evt);       
    347520                break;
    348521
     
    353526        return kSM_FatalError;
    354527}
    355 /****************************************************************
    356  *
    357  * DATA LOGGER'S INFOHANDLER
    358  *
    359  ****************************************************************/
     528// --------------------------------------------------------------------------
     529//
     530//! Inherited from DimInfo. Handles all the Infos to which we subscribed, and log them
     531//
    360532void DataLogger::infoHandler()
    361533{
    362534        DimInfo* I = getInfo();
    363         //there I should get the services updates. It remains unclear whether I will be getting the new services or not through here
    364 //      CheckForServicesUpdate(); //in this function I will add/remove services subscription
     535        if (I==NULL)
     536        {
     537                CheckForServicesUpdate();
     538                return;
     539        }
     540        //check if the service pointer corresponds to something that we subscribed to
     541        //this is a fix for a bug that provides bad Infos when a server starts
     542        bool found = false;
     543        SubscriptionsListType::iterator x;
     544        std::map<std::string, SubscriptionType>::iterator y;
     545        for (x=fServiceSubscriptions.begin(); x != fServiceSubscriptions.end(); x++)
     546        {//instead of extracting the server and service names, I crawl through my records. dunno what's faster, but both should work
     547                for (y=x->second.begin(); y!=x->second.end();y++)
     548                        if (y->second.dimInfo == I)
     549                        {
     550                                found = true;   
     551                                break;
     552                        }
     553                if (found)
     554                        break;
     555        }
     556        if (!found)
     557                return;
     558        if (I->getSize() <= 0)
     559                return;
     560        //check that the message has been updated by something, i.e. must be different from its initial value
     561        if (I->getTimestamp() == 0)
     562                return;
     563
    365564        CheckForRunNumber(I);
    366         LogPlease(I);
    367 }
    368 //! Checks for changes in the existingn services
    369 //! @todo finish this function as most of it is still missing (plus what is already there isn't great)
    370 void DataLogger::CheckForServicesUpdate()
    371 {//TODO well... do it...
    372  //TODO handle the cases were one server/service was removed and one was added
    373          const std::vector<std::string> serverList = fServiceList.GetServerList();
    374          if (serverList.size() != fServiceSubscriptions.size())
    375          {//some servers were added/deleted. Rebuild the list entirely
    376 std::cout << "Redoing the server list entirely " << serverList.size() << " " << fServiceSubscriptions.size() << std::endl;
    377                         std::map<std::string, std::vector<DimStampedInfo> >::iterator it;
    378                         for (it=fServiceSubscriptions.begin(); it != fServiceSubscriptions.end(); it++)
    379                                 (*it).second.clear();   
    380                         fServiceSubscriptions.clear();
    381                         InitServiceSubscription();
    382                         return;
    383          }
    384          //TODO crawl the list to see if any of the servers has updated its service list
    385        
    386 }
    387 //! Looks whether the currently being processed DimInfo indeed is a run number or not
     565        ReportPlease(I, y->second);
     566}
     567
     568// --------------------------------------------------------------------------
     569//
     570//! Checks whether or not the current info is a run number.
     571//! If so, then remember it. A run number is required to open the run-log file
     572//! @param I
     573//!             the current DimInfo
     574//
    388575void DataLogger::CheckForRunNumber(DimInfo* I)
    389576{
    390577        return;
    391         if (strstr(I->getName(), runNumberInfo) != NULL)
     578        if (strstr(I->getName(), fRunNumberInfo) != NULL)
    392579        {//assumes that the run number is an integer
    393580                //TODO check the format here
    394                 runNumber = I->getInt();       
    395         }
    396 }
    397 /****************************************************************
    398  *
    399  * DATA LOGGER'S RUN LOG
    400  *
    401  * write info to run log. Go to error if anything goes wrong
    402  *
    403  ****************************************************************/
    404  //! write info to logs. Go to error if anything goes wrong
    405 void DataLogger::LogPlease(DimInfo* I)
    406 {
    407         if (I->getSize() == 0)
     581                fRunNumber = I->getInt();       
     582        }
     583}
     584// --------------------------------------------------------------------------
     585//
     586//! write infos to log files.
     587//! @param I
     588//!     The current DimInfo
     589//
     590void DataLogger::ReportPlease(DimInfo* I, SubscriptionType& sub)
     591{
     592        //should we log or report this info ? (i.e. is it a message ?)
     593        bool isItaReport = ((strstr(I->getName(), "Message") == NULL) && (strstr(I->getName(), "MESSAGE") == NULL));
     594       
     595//      std::ofstream & dailyFile = fDailyReportFile;//isItaReport? fDailyReportFile : fDailyLogFile;
     596//      std::ofstream & runFile = fRunReportFile;//isItaReport? fRunReportFile : fRunLogFile;
     597
     598        //TODO add service exclusion
     599        if (!fDailyReportFile.is_open())
    408600                return;
    409         //TODO add service exclusion
    410        
    411         if (!fDailyFile.is_open())
    412                 return;
     601               
    413602        //construct the header
    414603        std::stringstream header;
    415         Time cTime((time_t)(I->getTimestamp()), 0);
    416         header << I->getName() << " " << cTime.Y() << " " << cTime.M() << " " << cTime.D() << " ";
    417         header << cTime.h() << " " << cTime.m() << " " << cTime.s() << " ";
    418         header << cTime.ms() << " " << I->getQuality() << " ";
    419        
    420         if (fDailyFile.is_open())
    421                 fDailyFile << header;
    422         if (fRunFile.is_open())
    423                 fRunFile << header;
    424        
    425        
    426         std::string text = ToString(I->getFormat(), I->getData(), I->getSize());
    427        
    428         if (!text.empty())
    429         {//replace bizarre characters by white space
     604       
     605        Time cTime((time_t)(I->getTimestamp()), I->getTimestampMillisecs());
     606
     607        //Buffer them for FITS write
     608        //TODO this has been replaced by MjD. So I guess that these member variables can go.
     609        fYear = cTime.Y(); fMonth = cTime.M(); fDay = cTime.D();
     610        fHour = cTime.h(); fMin = cTime.m(); fSec = cTime.s();
     611        fMs = cTime.ms(); fQuality = I->getQuality();
     612       
     613        fMjD = cTime.Mjd();
     614       
     615        if (isItaReport)
     616        {
     617                //write text header
     618                header << I->getName() << " " << fQuality << " ";
     619                header << fYear << " " << fMonth << " " << fDay << " ";
     620                header << fHour << " " << fMin << " " << fSec << " ";
     621                header << fMs << " " << I->getTimestamp() << " ";
     622
     623                Converter conv(std::cout, I->getFormat(), I->getData(), I->getSize());
     624
     625                if (conv.Ptr() == NULL)
     626                        return;
     627               
     628                std::string text(conv.Ptr());
     629       
     630                if (text.empty())
     631                        return;
     632       
     633                if (fDailyReportFile.is_open())
     634                        fDailyReportFile << header.str();
     635                if (fRunReportFile.is_open())
     636                        fRunReportFile << header.str();
     637       
     638                //replace bizarre characters by white space
    430639                for (unsigned int i=0; i<text.size(); i++)
    431640                {
     
    436645                                        text[i] = ' '; 
    437646                }
    438                 if (fDailyFile.is_open())
    439                         fDailyFile << text;
    440                 if (fRunFile.is_open())
    441                         fRunFile << text;
     647                if (fDailyReportFile.is_open())
     648                        fDailyReportFile << text << std::endl;
     649                if (fRunReportFile.is_open())
     650                        fRunReportFile << text << std::endl;
    442651        }
    443652        else
    444653        {
    445                 if (fDailyFile.is_open())
    446                         fDailyFile << "Cannot interpret service format" << std::endl;
    447                 if (fRunFile.is_open())
    448                         fRunFile << "Cannot interpret service format" << std::endl;
    449         }
    450 }
    451 //! Translates DIM data safely to string (assures no invalid memory accesses are made)
    452 //! Was mostly copied from DColl.cc
    453 std::string DataLogger::ToString(const char *format, const void *data, int size) {
    454 
    455   std::ostringstream Text;
    456  
    457   // Structure: print hex representation
    458   if (strlen(format) != 1) {
    459         for (int i=0; i<size; i++) {
    460           Text << std::setw(2) << std::hex << *((char *) data + i) << " ";
    461         }
    462         return Text.str();
    463   }
    464 
    465   // String if format "C" and terminated with \0
    466   if (strcmp(format, "C") == 0 && size > 0 && *((char *) data+size-1)=='\0') {
    467         return std::string((char *) data);
    468   }
    469 
    470   // Number array
    471   int ElementSize;
    472   switch (*format) {
    473     case 'C': ElementSize = sizeof(char);               break;
    474     case 'I':
    475     case 'L': ElementSize = sizeof(int);                break;
    476     case 'S': ElementSize = sizeof(short);              break;
    477     case 'F': ElementSize = sizeof(float);              break;
    478     case 'D': ElementSize = sizeof(double);             break;
    479     case 'X': ElementSize = sizeof(long long);  break;
    480     default: return std::string();
    481   }
    482 
    483   for (int i=0; i<size/ElementSize; i++) {
    484         // Space between entries
    485     if (i != 0) Text << " ";
    486 
    487         // Translate data
    488         switch (*format) {
    489       case 'C': Text << *((char *) data + i);           break;
    490       case 'I':
    491       case 'L': Text << *((int *) data + i);            break;
    492       case 'S': Text << *((short *) data + i);          break;
    493       case 'F': Text << *((float *) data + i);          break;
    494       case 'D': Text << *((double *) data + i);         break;
    495       case 'X': Text << *((long long *) data + i);      break;
    496         }
    497   }
    498  
    499   return Text.str();
    500 }
    501 //! write messages to logs. Go to error if anything goes wrong
     654                std::string n = I->getName();
     655                std::stringstream msg;
     656                msg << n.substr(0, n.find_first_of('/')) << ": " << I->getString();
     657                MessageImp dailyMess(fDailyLogFile);
     658                dailyMess.Write(cTime, msg.str().c_str(), fQuality);
     659                if (fRunLogFile.is_open())
     660                {
     661                        MessageImp runMess(fRunLogFile);
     662                        runMess.Write(cTime, msg.str().c_str(), fQuality);
     663                }
     664        }
     665
     666        if (!sub.dailyFile.IsOpen() || !sub.runFile.IsOpen())
     667                OpenFITSFilesPlease(sub);       
     668        WriteToFITS(sub);
     669       
     670
     671}
     672// --------------------------------------------------------------------------
     673//
     674//! write messages to logs.
     675//! @param evt
     676//!             the current event to log
     677//! @returns
     678//!             the new state. Currently, always the current state
     679//
     680//DEPREC I guess that this function should not be any longer
    502681int DataLogger::LogMessagePlease(const Event& evt)
    503682{
    504         if (!fDailyFile.is_open())
     683        if (!fDailyLogFile.is_open())
    505684                return GetCurrentState();
    506685       
     
    510689        header << cTime.h() << " " << cTime.m() << " " << cTime.s() << " ";
    511690        header << cTime.ms() << " ";
    512        
    513         if (fDailyFile.is_open())
    514                 fDailyFile << header;
    515         if (fRunFile.is_open())
    516                 fRunFile << header;
    517        
    518         std::string text = ToString(evt.GetFormat().c_str(), evt.GetData(), evt.GetSize());
     691               
     692//      std::string text = ToString(evt.GetFormat().c_str(), evt.GetData(), evt.GetSize());
     693        Converter conv(std::cout, evt.GetFormat().c_str(), evt.GetData(), evt.GetSize());
     694        if (conv.Ptr() == NULL)
     695                return GetCurrentState();
     696               
     697        std::string text(conv.Ptr());
    519698       
    520699        if (!text.empty())
    521         {//replace bizarre characters by white space
     700        {
     701                if (fDailyLogFile.is_open())
     702                        fDailyLogFile << header;
     703                if (fRunLogFile.is_open())
     704                        fRunLogFile << header;
     705               
     706                //replace bizarre characters by white space
    522707                for (unsigned int i=0; i<text.size(); i++)
    523708                {
     
    528713                                        text[i] = ' '; 
    529714                }
    530                 if (fDailyFile.is_open())
    531                         fDailyFile << text;
    532                 if (fRunFile.is_open())
    533                         fRunFile << text;
    534         }
     715                if (fDailyLogFile.is_open())
     716                        fDailyLogFile << text;
     717                if (fRunLogFile.is_open())
     718                        fRunLogFile << text;
     719        }
     720       
     721        return GetCurrentState();       
     722}
     723// --------------------------------------------------------------------------
     724//
     725//!     Sets the path to use for the daily log file.
     726//! @param evt
     727//!     the event transporting the path
     728//! @returns
     729//!             currently only the current state.
     730//
     731int DataLogger::ConfigureDailyFileName(const Event& evt)
     732{
     733        if (evt.GetText() != NULL)
     734                fDailyFileName = std::string(evt.GetText());   
    535735        else
    536         {
    537                 if (fDailyFile.is_open())
    538                         fDailyFile << "Cannot interpret log message format" << std::endl;
    539                 if (fRunFile.is_open())
    540                         fRunFile << "Cannot interpret log message format" << std::endl;
    541         }       
    542        
    543         return GetCurrentState();       
    544 }
    545 /****************************************************************
    546  *
    547  * DATA LOGGER'S RUN LOG
    548  */
    549  //!Set the current daily file name. This will NOT close any file
    550  /*
    551  ****************************************************************/
    552 int DataLogger::ConfigureDailyFileName(const Event& evt)
    553 {
    554         fDailyFileName = std::string(evt.GetText());   
     736                Error("Empty daily folder");
     737
    555738        return GetCurrentState();
    556739}
    557 /****************************************************************
    558  *
    559  * DATA LOGGER'S CONFIGURE RUN FILE NAME
    560  *
    561  */
    562  //! Set the current run folder name. This will NOT close any file
    563  /*
    564  ****************************************************************/
     740// --------------------------------------------------------------------------
     741//
     742//! Sets the path to use for the run log file.
     743//! @param evt
     744//!             the event transporting the path
     745//! @returns
     746//!     currently only the current state
    565747int DataLogger::ConfigureRunFileName(const Event& evt)
    566748{
    567         fRunFileName = std::string(evt.GetText());
     749        if (evt.GetText() != NULL)
     750                fRunFileName = std::string(evt.GetText());
     751        else
     752                Error("Empty daily folder");
     753
    568754        return GetCurrentState();
    569755}
    570 /****************************************************************
    571  *
    572  * DATA LOGGER'S CONFIGURE RUN NUMBER
    573  *
    574  */
    575  //! set the current run number. This will NOT close any file.
    576  /*
    577  ****************************************************************/
     756// --------------------------------------------------------------------------
     757//
     758//! Sets the run number.
     759//! @param evt
     760//!             the event transporting the run number
     761//! @returns
     762//!     currently only the current state
    578763int DataLogger::ConfigureRunNumber(const Event& evt)
    579764{
    580         runNumber = evt.GetInt();
    581         //TODO replace the run number in the filename if already exist. Otherwise just append it
     765        fRunNumber = evt.GetInt();
     766
    582767        return GetCurrentState();
    583768}
    584 /****************************************************************
    585  *
    586  * DATA LOGGER'S START PLEASE
    587  *
    588  */
    589  //! Implements the start transition
    590  /*
    591  ****************************************************************/
     769// --------------------------------------------------------------------------
     770//
     771//! Implements the Start transition.
     772//! Concatenates the given path for the daily file and the filename itself (based on the day),
     773//! and tries to open it.
     774//! @returns
     775//!             kSM_DailyOpen if success, kSM_BadDailyConfig if failure
    592776int DataLogger::StartPlease()
    593777{
     
    598782        std::string fullName = fDailyFileName + '/' + sTime.str() + ".log";
    599783       
    600         fDailyFile.open(fullName.c_str(), std::ios_base::out | std::ios_base::ate); //maybe should be "app" instead of "ate" ??
    601         if (!fDailyFile.is_open())
     784        fDailyLogFile.open(fullName.c_str(), std::ios_base::out | std::ios_base::app); //maybe should be "app" instead of "ate" ??
     785        fullName = fDailyFileName + '/' + sTime.str() + ".rep";
     786        fDailyReportFile.open(fullName.c_str(), std::ios_base::out | std::ios_base::app);
     787        if (!fDailyLogFile.is_open() || !fDailyReportFile.is_open())
    602788        {
    603789                //TODO send an error message   
     
    606792        return kSM_DailyOpen;   
    607793}
    608 /****************************************************************
    609  *
    610  * DATA LOGGER'S STOP PLEASE
    611  *
    612  */
    613  //! Implements the stop transition
    614  /*
    615  ****************************************************************/
    616 int DataLogger::StopPlease()
    617 {
    618         if (fDailyFile.is_open())
    619                 fDailyFile.close();
    620                
    621         if (fRunFile.is_open())
    622             fRunFile.close();   
    623            
    624         return kSM_Ready;
    625 
    626 }
    627 /****************************************************************
    628  *
    629  * DATA LOGGER'S START RUN PLEASE
    630  *
    631  */
    632  //! Implements the start run transtition
    633  /*
    634  ****************************************************************/
     794// --------------------------------------------------------------------------
     795//
     796//! open if required a the FITS files corresponding to a given subscription
     797//! @param sub
     798//!     the current DimInfo subscription being examined
     799void DataLogger::OpenFITSFilesPlease(SubscriptionType& sub)
     800{
     801        std::string serviceName(sub.dimInfo->getName());
     802        for (unsigned int i=0;i<serviceName.size(); i++)
     803        {
     804                if (serviceName[i] == '/')
     805                {
     806                        serviceName[i] = '_';
     807                        break; 
     808                }       
     809        }
     810        Time time;
     811        std::stringstream sTime;
     812        sTime << time.Y() << "_" << time.M() << "_" << time.D();
     813        //we open the dailyFile anyway, otherwise this function shouldn't have been called.
     814        if (!sub.dailyFile.IsOpen())
     815        {
     816                std::string partialName = fDailyFileName + '/' + sTime.str() + '_' + serviceName + ".fits";
     817                std::string fullName = fDailyFileName + '/' + sTime.str() + '_' + serviceName + ".fits[" + serviceName + "]";
     818
     819                AllocateFITSBuffers(sub);
     820                //currently, the FITS are written in the same directory as the text files.
     821                //thus the write permissions have already been checked by the text files.
     822                //if the target folder changes, then I should check the write permissions here
     823                //now we only check whether the target file exists or not
     824                std::ifstream readTest(partialName.c_str());
     825                if (readTest.is_open())
     826                {
     827                        readTest.close();
     828                        sub.dailyFile.Open(fullName.c_str(), "UPDATE");
     829                }
     830                else {
     831                        sub.dailyFile.Open(fullName.c_str(), "CREATE"); 
     832                }
     833               
     834//TODO Write the header's attributes
     835        }
     836        if (!sub.runFile.IsOpen() && (GetCurrentState() == kSM_Logging))
     837        {//buffer for the run file have already been allocated when doing the daily file
     838                std::stringstream sRun;
     839                sRun << fRunNumber;
     840                std::string partialName = fRunFileName + '/' + sRun.str() + '_' + serviceName + ".fits";
     841                std::string fullName = fRunFileName + '/' +  sRun.str() + '_' + serviceName + ".fits[" + serviceName + "]";
     842               
     843                std::ifstream readTest(partialName.c_str());
     844                if (readTest.is_open())
     845                {
     846                        readTest.close();
     847                        sub.runFile.Open(fullName.c_str(), "UPDATE");
     848                }
     849                else
     850                        sub.runFile.Open(fullName.c_str(), "CREATE");
     851//TODO Write the header's attributes
     852        }
     853}       
     854// --------------------------------------------------------------------------
     855//
     856void DataLogger::AllocateFITSBuffers(SubscriptionType& sub)
     857{
     858         const char* format = sub.dimInfo->getFormat();
     859         const int size = sub.dimInfo->getSize();
     860         
     861         //Init the time columns of the file
     862         sub.dailyFile.InitCol("Date", "double", &fMjD);
     863         sub.runFile.InitCol("Date", "double", &fMjD);
     864         
     865//       sub.dailyFile.InitCol("Year", "short", &fYear);
     866//       sub.dailyFile.InitCol("Month", "short", &fMonth);
     867//       sub.dailyFile.InitCol("Day", "short", &fDay);
     868//       sub.dailyFile.InitCol("Hour", "short", &fHour);
     869//       sub.dailyFile.InitCol("Minute", "short", &fMin);
     870//       sub.dailyFile.InitCol("Second", "short", &fSec);
     871//       sub.dailyFile.InitCol("MilliSec", "int", &fMs);
     872         sub.dailyFile.InitCol("QoS", "int", &fQuality);
     873
     874//       sub.runFile.InitCol("Year", "short", &fYear);
     875//       sub.runFile.InitCol("Month", "short", &fMonth);
     876//       sub.runFile.InitCol("Day", "short", &fDay);
     877//       sub.runFile.InitCol("Hour", "short", &fHour);
     878//       sub.runFile.InitCol("Minute", "short", &fMin);
     879//       sub.runFile.InitCol("Second", "short", &fSec);
     880//       sub.runFile.InitCol("MilliSec", "int", &fMs);
     881         sub.runFile.InitCol("QoS", "int", &fQuality);
     882         
     883         Converter::FormatList flist = Converter::Convert(std::cout, std::string(format));
     884         
     885         //we've got a nice structure describing the format of this service's messages.
     886         //Let's create the appropriate FITS columns
     887         for (unsigned int i=0;i<flist.size();i++)
     888         {
     889                std::stringstream colName;
     890                std::stringstream dataQualifier;
     891                void * dataPointer = static_cast<char*>(sub.dimInfo->getData()) + flist[i].second.second;
     892                colName << "Data" << i;
     893                dataQualifier << flist[i].second.first;
     894                switch (flist[i].first.first)
     895                {
     896                        case 'c':
     897                                dataQualifier <<  "S";
     898                        break;
     899                        case 's':
     900                                dataQualifier << "I";
     901                        break;
     902                        case 'i':
     903                                dataQualifier << "J";
     904                        break;
     905                        case 'l':
     906                                dataQualifier << "J";
     907                                //TODO triple check that in FITS, long = int
     908                        break;
     909                        case 'f':
     910                                dataQualifier << "E";
     911                        break;
     912                        case 'd':
     913                                dataQualifier << "D";
     914                        break;
     915                        case 'x':
     916                                dataQualifier << "K";
     917                        break;
     918                        case 'S':
     919                                //for strings, the number of elements I get is wrong. Correct it
     920                                dataQualifier.str(""); //clear
     921                                dataQualifier << size-1 <<  "A";
     922                        break;
     923                       
     924                        default:
     925                                Error("THIS SHOULD NEVER BE REACHED. dataLogger.cc ln 962.");
     926                };
     927                sub.dailyFile.InitCol(colName.str().c_str(), dataQualifier.str().c_str(), dataPointer);
     928                sub.runFile.InitCol(colName.str().c_str(), dataQualifier.str().c_str(), dataPointer);
     929         }
     930
     931//TODO init the attributes
     932}
     933// --------------------------------------------------------------------------
     934//
     935//! write a dimInfo data to its corresponding FITS files
     936//
     937void DataLogger::WriteToFITS(SubscriptionType& sub)
     938{
     939                //dailyFile status (open or not) already checked
     940                if (sub.dailyFile.IsOpen())
     941                        sub.dailyFile.Write();
     942                if (sub.runFile.IsOpen())
     943                        sub.runFile.Write();
     944}
     945// --------------------------------------------------------------------------
     946//
     947//! Implements the StartRun transition.
     948//! Concatenates the given path for the run file and the filename itself (based on the run number),
     949//! and tries to open it.
     950//! @returns
     951//!             kSM_Logging if success, kSM_BadRunConfig if failure.
    635952int DataLogger::StartRunPlease()
    636953{
    637954        //attempt to open run file with current parameters
    638         if (runNumber == -1)
     955        if (fRunNumber == -1)
    639956                return kSM_BadRunConfig;
    640957        std::stringstream sRun;
    641         sRun << runNumber;
     958        sRun << fRunNumber;
    642959        std::string fullName = fRunFileName + '/' + sRun.str() + ".log";
    643 
    644         fRunFile.open(fullName.c_str(), std::ios_base::out | std::ios_base::ate); //maybe should be app instead of ate
    645         if (!fRunFile.is_open())
     960        fRunLogFile.open(fullName.c_str(), std::ios_base::out | std::ios_base::app); //maybe should be app instead of ate
     961
     962        fullName = fRunFileName + '/' + sRun.str() + ".rep";
     963        fRunReportFile.open(fullName.c_str(), std::ios_base::out | std::ios_base::app);
     964       
     965        if (!fRunLogFile.is_open() || !fRunReportFile.is_open())
    646966        {
    647967                //TODO send an error message
     
    651971        return kSM_Logging;
    652972}
    653 /****************************************************************
    654  *
    655  * DATA LOGGER'S STOP RUN PLEASE
    656  *
    657  */
    658  //! Implements the stop run transition
    659  /*
    660  ****************************************************************/
     973// --------------------------------------------------------------------------
     974//
     975//! Implements the StopRun transition.
     976//! Attempts to close the run file.
     977//! @returns
     978//!             kSM_WaitingRun if success, kSM_FatalError otherwise
    661979int DataLogger::StopRunPlease()
    662980{
    663         if (!fRunFile.is_open())
     981        if (!fRunLogFile.is_open() || !fRunReportFile.is_open())
    664982                return kSM_FatalError;
    665983       
    666         fRunFile.close();
    667        
     984        fRunLogFile.close();
     985        fRunReportFile.close();
     986        for (SubscriptionsListType::iterator i = fServiceSubscriptions.begin(); i != fServiceSubscriptions.end(); i++)
     987                for (std::map<std::string, SubscriptionType>::iterator j = i->second.begin(); j != i->second.end(); j++)
     988                {
     989                                if (j->second.runFile.IsOpen())
     990                                        j->second.runFile.Close();     
     991                }
    668992        return kSM_WaitingRun;
    669993
    670994}
    671 /****************************************************************
    672  *
    673  * DATA LOGGER'S RESET PLEASE
    674  *
    675  */
    676  //! Implements the reset transition
    677  /*
    678  ****************************************************************/
    679 int DataLogger::ResetPlease()
    680 {
    681         if (fDailyFile.is_open())
    682                 fDailyFile.close();
    683 
    684         if (fRunFile.is_open())
    685                 fRunFile.close();
    686                        
     995// --------------------------------------------------------------------------
     996//
     997//! Implements the Stop and Reset transitions.
     998//! Attempts to close any openned file.
     999//! @returns
     1000//!     kSM_Ready
     1001int DataLogger::GoToReadyPlease()
     1002{
     1003        if (fDailyLogFile.is_open())
     1004                fDailyLogFile.close();
     1005        if (fDailyReportFile.is_open())
     1006                fDailyReportFile.close();
     1007
     1008        if (fRunLogFile.is_open())
     1009                fRunLogFile.close();
     1010        if (fRunReportFile.is_open())
     1011                fRunReportFile.close();
     1012               
     1013        for (SubscriptionsListType::iterator i = fServiceSubscriptions.begin(); i != fServiceSubscriptions.end(); i++)
     1014                for (std::map<std::string, SubscriptionType>::iterator j = i->second.begin(); j != i->second.end(); j++)
     1015                {
     1016                                if (j->second.dailyFile.IsOpen())
     1017                                        j->second.dailyFile.Close();
     1018                                if (j->second.runFile.IsOpen())
     1019                                        j->second.runFile.Close();     
     1020                }
    6871021        return kSM_Ready;
    6881022}
    689 //! Implements the Daily to WaitRun transition
     1023// --------------------------------------------------------------------------
     1024//
     1025//! Implements the transition towards kSM_WaitingRun
     1026//! Does nothing really.
     1027//!     @returns
     1028//!             kSM_WaitingRun
    6901029int DataLogger::DailyToWaitRunPlease()
    6911030{
    6921031        return kSM_WaitingRun; 
    6931032}
    694 /*
    695 bool DataLogger::ServiceOk(DimInfo* item)
    696 {
    697         return !((item->getSize() == strlen(NO_LINK)+1) && (memcmp(item->getData(), NO_LINK, item->getSize()) == 0));   
    698 }*/
    699 /****************************************************************
    700  *
    701  * MAIN
    702  *
    703  ****************************************************************/
    704 extern bool CheckDim(bool=true);
    705  
     1033
     1034// --------------------------------------------------------------------------
     1035//
    7061036int main()
    7071037{
    708         std::cout << "Data Logger Starting" << std::endl;
    709        
    710         if (!CheckDim())
    711                 return -1;
    712        
    713         std::cout << "Continuing" << std::endl;
     1038//No more Dim Checking ??
     1039//      if (!CheckDim())
     1040//              return -1;
     1041       
    7141042        DataLogger log;
    715         std::cout << "DataLogger created. Starting main loop" << std::endl;
    716         while (!log.IsRExitRequested())
    717         {
    718                                 usleep(1);
     1043        while (!log.fExitRequested)
     1044        {
     1045                usleep(10);
    7191046        }
    7201047        return 0;
Note: See TracChangeset for help on using the changeset viewer.