Index: /trunk/FACT++/src/dataLogger.cc
===================================================================
--- /trunk/FACT++/src/dataLogger.cc	(revision 10898)
+++ /trunk/FACT++/src/dataLogger.cc	(revision 10899)
@@ -96,14 +96,18 @@
 ///Run number record. Used to keep track of which run numbers are still active
 struct RunNumberType {
+#ifdef RUN_LOGS
     ///the run number log file
-    ofstream* logFile;
+    shared_ptr<ofstream> logFile;
+#endif
     ///the run number report file
-    ofstream* reportFile;
+    shared_ptr<ofstream> reportFile;
 #ifdef HAVE_FITS
     ///the run number group fits file
-    CCfits::FITS* runFitsFile;
-#endif
+    shared_ptr<CCfits::FITS> runFitsFile;
+#endif
+#ifdef RUN_LOGS
     ///the log filename
     string logName;
+#endif
     ///the report filename
     string reportName;
@@ -112,6 +116,4 @@
     ///the time at which the run number was received
     Time time;
-    ///internal counter used for smart referencing
-    int* numCopies;
     ///list of opened fits used to create the fits grouping when the run ends
     map<string, vector<string> > openedFits;
@@ -119,77 +121,49 @@
     RunNumberType()
     {
-        logFile = new ofstream();
-        reportFile = new ofstream();
+#ifdef RUN_LOGS
+        logFile = shared_ptr<ofstream>(new ofstream());
+#endif
+        reportFile = shared_ptr<ofstream>(new ofstream());
 #ifdef HAVE_FITS
-        runFitsFile = NULL;
+        runFitsFile = shared_ptr<CCfits::FITS>();
 #endif
         runNumber = 0;
         //give it a meaningless, 0 time to distinguish with actual, valid times
         time = Time(0,0);
-        numCopies = new int(1);
     }
     ///default destructor
     ~RunNumberType()
     {
-        if (numCopies)
-        {
-            (*numCopies)--;
-            if (*numCopies < 1)
-            {
-                if (logFile)
-                {
-                    if (logFile->is_open())
-                        logFile->close();
-                    delete logFile;
-                    logFile = NULL;
-                }
-                if (reportFile)
-                {
-                    if (reportFile->is_open())
-                        reportFile->close();
-                    delete reportFile;
-                    reportFile = NULL;
-                }
-#ifdef HAVE_FITS
-                if (runFitsFile)
-                {
-                    delete runFitsFile;
-                    runFitsFile = NULL;
-                }
-#endif
-                delete numCopies;
-                numCopies = NULL;
-            }
-        }
+
     }
     ///copy operator
     void operator = (const RunNumberType& other)
     {
+#ifdef RUN_LOGS
         logFile = other.logFile;
+        logName = other.logName;
+#endif
         reportFile = other.reportFile;
-        logName = other.logName;
         reportName = other.reportName;
         runNumber = other.runNumber;
         time = other.time;
-        numCopies = other.numCopies;
 #ifdef HAVE_FITS
         runFitsFile = other.runFitsFile;
 #endif
-        (*numCopies)++;
     }
     ///copy constructor
     RunNumberType(const RunNumberType& other)
     {
+#ifdef RUN_LOGS
         logFile = other.logFile;
+        logName = other.logName;
+#endif
         reportFile = other.reportFile;
-        logName = other.logName;
         reportName = other.reportName;
         runNumber = other.runNumber;
         time = other.time;
-        numCopies = other.numCopies;
 #ifdef HAVE_FITS
         runFitsFile = other.runFitsFile;
 #endif
-        (*numCopies)++;
     }
 
@@ -220,5 +194,5 @@
 #endif
     ///the actual dimInfo pointer
-    DimStampedInfo* dimInfo;
+    shared_ptr<DimStampedInfo> dimInfo;
     ///the server
     string server;
@@ -226,7 +200,5 @@
     string service;
     ///the converter for outputting the data according to the format
-    Converter* fConv;
-    ///internal counter used for smart referencing
-    int* numCopies;
+    shared_ptr<Converter> fConv;
     ///the current run number used by this subscription
     uint32_t runNumber;
@@ -241,8 +213,6 @@
         server = other.server;
         service = other.service;
-        numCopies = other.numCopies;
         fConv = other.fConv;
         runNumber = other.runNumber;
-        (*numCopies)++;
     }
     ///copy constructor
@@ -256,48 +226,24 @@
         server = other.server;
         service = other.service;
-        numCopies = other.numCopies;
         fConv = other.fConv;
         runNumber = other.runNumber;
-        (*numCopies)++;
     }
     ///Dim info constructor
     SubscriptionType(DimStampedInfo* info)
     {
-        dimInfo = info;
-        fConv = NULL;
+        dimInfo = shared_ptr<DimStampedInfo>(info);
+        fConv = shared_ptr<Converter>();
         runNumber = 0;
-        numCopies = new int(1);
     }
     ///default constructor
     SubscriptionType()
     {
-        dimInfo = NULL;
-        fConv = NULL;
+        dimInfo = shared_ptr<DimStampedInfo>();
+        fConv = shared_ptr<Converter>();
         runNumber = 0;
-        numCopies = new int(1);
     }
     ///default destructor
     ~SubscriptionType()
     {
-        if (numCopies)
-            (*numCopies)--;
-        if (numCopies)
-        if (*numCopies < 1)
-        {
-            if (dimInfo)
-            delete dimInfo;
-#ifdef HAVE_FITS
-            if (nightlyFile.IsOpen())
-                nightlyFile.Close();
-            if (runFile.IsOpen())
-                runFile.Close();
-#endif
-            if (numCopies)
-            delete numCopies;
-            delete fConv;
-            fConv = NULL;
-            dimInfo = NULL;
-            numCopies = NULL;
-        }
     }
 };
@@ -473,4 +419,12 @@
     ///retrieves the size of a file
     off_t GetFileSize(string&);
+    ///Get the digits of year, month and day for filenames and paths
+    void GetYearMonthDayForFiles(unsigned short& year, unsigned short& month, unsigned short& day);
+    ///Appends the relevant year month day to a given path
+    void AppendYearMonthDaytoPath(string& path);
+    ///Form the base nightly path
+    void FormBaseNightlyPath(string& path);
+    ///Form the base run path
+    void FormBaseRunPath(string& path, const int runNumber);
     ///Form the base (without extension) name of the nightly text files (logs and reports)
     void FormBaseNightlyTextFileName(string& name);
@@ -501,4 +455,8 @@
     ///Checks if the input osftream is in error state, and if so close it.
     void CheckForOfstreamError(ofstream& out);
+    ///Checks if a given path exist
+    bool DoesPathExist(string path);
+    ///Create a given directory
+    bool CreateDirectory(string path);
     /***************************************************
     * INHERITED FROM DIMSERVICEINFOLIST
@@ -514,9 +472,44 @@
 // --------------------------------------------------------------------------
 //
+//! Check if a given path exists
+//! @param path the path to be checked
+//! @return whether or not the creation has been successfull
+//
+bool DataLogger::CreateDirectory(string path)
+{
+    mode_t rightsMask = S_IRWXU | S_IXGRP | S_IRGRP | S_IXOTH | S_IROTH; //everybody read, owner writes
+
+    int returnValue = mkdir(path.c_str(), rightsMask);
+
+    if (returnValue != 0)
+    {
+        ostringstream str;
+        str << "Could not create directory " << path << " mkdir error code: " << errno;
+        Error(str.str());
+        return false;
+    }
+
+    return true;
+}
+// --------------------------------------------------------------------------
+//
+//! Check if a given path exists
+//! @param path the path to be checked
+//! @return whether or not the given path exists
+//
+bool DataLogger::DoesPathExist(string path)
+{
+    struct stat st;
+    if(stat(path.c_str(),&st) == 0)
+        return true;
+
+    return false;
+}
+// --------------------------------------------------------------------------
+//
 //! Add a new service subscription
 //! @param server the server for which the subscription should be created
 //! @param service the service for which the subscription should be created
 //! @param isCmd whether this is a Dim Command or not. Commands are not logged
-//TODO maybe commands should indeed be logged ?
 //
 void DataLogger::AddService(const string& server, const string& service, const string&, bool isCmd)
@@ -525,35 +518,23 @@
     if (!ShouldSubscribe(server, service))
         return;
-    //dataLogger does not subscribe to commands
+
+         //dataLogger does not subscribe to commands
     if (isCmd)
         return;
-    //do we already have an entry for that server ?
-    SubscriptionsListType::iterator cSubs = fServiceSubscriptions.find(server);
-    if (cSubs != fServiceSubscriptions.end())
-    {//server already here. check its services
-        if (cSubs->second.find(service) == cSubs->second.end())
-        {//service not found. Add it
-            cSubs->second[service].dimInfo = SubscribeToPlease(server, service);
-            cSubs->second[service].server = server;
-            cSubs->second[service].service = service;
-        }
-        else
-        {
-            MessageImp::Error("Service " + server + "/" + service + " is already in the dataLogger's list. ignoring its update.");
-            return;
-        }
-    }
-    else
-    {//server not yet in our list. add it
-        fServiceSubscriptions[server] = map<string, SubscriptionType>();
-        map<string, SubscriptionType>& liste = fServiceSubscriptions[server];
-        liste[service].dimInfo = SubscribeToPlease(server, service);
-        liste[service].server = server;
-        liste[service].service = service;
-    }
+
+    map<string, SubscriptionType> &list = fServiceSubscriptions[server];
+
+    if (list.find(service) != list.end())
+    {
+        Error("Service " + server + "/" + service + " is already in the dataLogger's list. ignoring its update.");
+        return;
+    }
+
+    list[service].dimInfo = shared_ptr<DimStampedInfo>(SubscribeToPlease(server, service));
+    list[service].server  = server;
+    list[service].service = service;
+
     if (fDebugIsOn)
-    {
         Debug("Added subscription to " + server + "/" + service);
-    }
 }
 // --------------------------------------------------------------------------
@@ -630,4 +611,5 @@
 string DataLogger::CheckIfDirIsDot(const string& dir)
 {
+    errno = 0;
     if (dir == ".")
     {
@@ -657,4 +639,5 @@
 void DataLogger::OpenTextFilePlease(ofstream& stream, const string& name)
 {
+    errno = 0;
     stream.open(name.c_str(), ios_base::out | ios_base::app);
     if (errno != 0)
@@ -714,5 +697,7 @@
     sRun << runNumber;
     fileName = sRun.str() + "_group.fits";
-    fileNameWithPath = fRunFilePath + '/' + fileName;
+    string path;
+    FormBaseRunPath(path, runNumber);
+    fileNameWithPath = path + '/' + fileName;
 }
 
@@ -727,14 +712,19 @@
 {
     ostringstream groupName;
+    string path;
     if (runNumber != 0)
     {
-        groupName << fRunFilePath << '/' << runNumber << ".fits";
+        FormBaseRunPath(path, runNumber);
+        groupName << path << '/' << runNumber << ".fits";
     }
     else
     {
-        Time time;
         ostringstream sTime;
-        sTime << time.Y() << "_" << time.M() << "_" << time.D();
-        groupName << fNightlyFilePath << '/' << sTime.str() << ".fits";
+        unsigned short year, month, day;
+        GetYearMonthDayForFiles(year, month, day);
+        sTime << year << "_" << month << "_" << day;
+        FormBaseNightlyPath(path);
+
+        groupName << path << '/' << sTime.str() << ".fits";
     }
     fileNameWithPath = groupName.str();
@@ -750,9 +740,12 @@
 void DataLogger::FormNightlyFitsFileName(string& fileName, string& fileNameWithPath, const string& serviceName)
 {
-    Time time;
     ostringstream sTime;
-    sTime << time.Y() << "_" << time.M() << "_" << time.D();
+    unsigned short year, month, day;
+    GetYearMonthDayForFiles(year, month, day);
+    sTime << year << "_" << month << "_" << day;
     fileName = sTime.str() + '_' + serviceName + ".fits";
-    fileNameWithPath = fNightlyFilePath + '/' + fileName;
+    string path;
+    FormBaseNightlyPath(path);
+    fileNameWithPath = path + '/' + fileName;
 }
 // --------------------------------------------------------------------------
@@ -769,5 +762,7 @@
     sRun << runNumber;
     fileName = sRun.str() + '_' + serviceName + ".fits";
-    fileNameWithPath = fRunFilePath + '/' + fileName;
+    string path;
+    FormBaseRunPath(path, runNumber);
+    fileNameWithPath = path + '/' + fileName;
 }
 // --------------------------------------------------------------------------
@@ -781,6 +776,7 @@
     ostringstream sRun;
     sRun << runNumber;
-
-    name = CheckIfDirIsDot(fRunFilePath) + '/' + sRun.str();
+    string path;
+    FormBaseRunPath(path, runNumber);
+    name = path + '/' + sRun.str();
 }
 // --------------------------------------------------------------------------
@@ -807,9 +803,12 @@
 void DataLogger::FormBaseNightlyTextFileName(string& name)
 {
-    Time time;
     ostringstream sTime;
-    sTime << time.Y() << "_" << time.M() << "_" << time.D();
-
-    name = CheckIfDirIsDot(fNightlyFilePath) + '/' + sTime.str();
+    unsigned short year, month, day;
+    GetYearMonthDayForFiles(year, month, day);
+    sTime << year << "_" << month << "_" << day;
+
+    FormBaseNightlyPath(name);
+
+    name += '/' + sTime.str();
 }
 // --------------------------------------------------------------------------
@@ -830,4 +829,120 @@
 // --------------------------------------------------------------------------
 //
+//!Fills in the correct values for naming files based on current date.
+//! It fills in the same values throughout a whole night for consistency
+//! @param year the year to be used for file names
+//! @param month the month to be used for file names
+//! @param day the day to be used for file names
+//
+void DataLogger::GetYearMonthDayForFiles(unsigned short& year, unsigned short& month, unsigned short& day)
+{
+    Time time;
+    year = time.Y();
+    month = time.M();
+    day = time.D();
+    bool shouldGoBackOneDay = false;
+    if (time.h() < 12) //we are currently before noon. go back one day
+        shouldGoBackOneDay = true;
+
+    if (shouldGoBackOneDay && (month == 1) && (day == 1))
+        year--;
+
+    if (shouldGoBackOneDay && (day == 1))
+    {
+        if (month != 1)
+            month--;
+        else
+            month = 12;
+    }
+
+    if (shouldGoBackOneDay)
+    {
+        if (day != 1)
+            day--;
+        else
+            switch (month)
+            {
+                case 1:
+                case 3:
+                case 5:
+                case 7:
+                case 8:
+                case 10:
+                case 12:
+                    day = 31;
+                break;
+                case 4:
+                case 6:
+                case 9:
+                case 11:
+                    day = 30;
+                break;
+                case 2:
+                    if (year == 2012 || year == 2016 || year == 2020 || year == 2024 || year == 2028 || year == 2032 || year == 2036 || year == 2040)
+                        day = 29;
+                    else
+                        day = 28;
+                break;
+            };
+    }
+
+
+}
+// --------------------------------------------------------------------------
+//
+//! Appends the appropriate year, month and day to a given path.
+//! creates the required directories if they do not already exist
+//! @param path the path to be augmented
+//
+void DataLogger::AppendYearMonthDaytoPath(string& path)
+{
+    ostringstream basePath;
+    unsigned short year, month, day;
+    GetYearMonthDayForFiles(year, month, day);
+
+    basePath << CheckIfDirIsDot(path) << '/' << year;
+    if (!DoesPathExist(basePath.str()))
+         CreateDirectory(basePath.str());
+
+     basePath << '/' << month;
+     if (!DoesPathExist(basePath.str()))
+         CreateDirectory(basePath.str());
+
+     basePath << '/' << day;
+     if (!DoesPathExist(basePath.str()))
+         CreateDirectory(basePath.str());
+
+     path = basePath.str();
+}
+// --------------------------------------------------------------------------
+//
+//! Forms the base path for putting nightly files in it
+//! @param the variable that should receive the path
+//
+void DataLogger::FormBaseNightlyPath(string& path)
+{
+    path = fNightlyFilePath;
+    AppendYearMonthDaytoPath(path);
+}
+// --------------------------------------------------------------------------
+//
+//! Forms the base path for putting run files in it
+//! @param the variable that should receive the path
+//! @runNumber the run number for which to create the path
+//
+void DataLogger::FormBaseRunPath(string& path, const int runNumber)
+{
+    path = fRunFilePath;
+    AppendYearMonthDaytoPath(path);
+
+    ostringstream basePath;
+    basePath << path << '/' << runNumber;
+    if (!DoesPathExist(basePath.str()))
+        CreateDirectory(basePath.str());
+
+    path = basePath.str();
+}
+// --------------------------------------------------------------------------
+//
 //!retrieves the size on disk of a file
 //! @param fileName the full file name for which the size on disk should be retrieved
@@ -836,4 +951,5 @@
 off_t DataLogger::GetFileSize(string& fileName)
 {
+    errno = 0;
     struct stat st;
     if (!stat(fileName.c_str(), &st))
@@ -935,6 +1051,8 @@
         if (it->reportFile->is_open())
             fFileSizesMap[it->reportName] = GetFileSize(it->reportName);
+#ifdef RUN_LOGS
         if (it->logFile->is_open())
             fFileSizesMap[it->logName] = GetFileSize(it->logName);
+#endif
     }
     struct statvfs vfs;
@@ -1222,5 +1340,5 @@
     {//find current service is subscriptions
         for (y=x->second.begin(); y!=x->second.end();y++)
-            if (y->second.dimInfo == I)
+            if ((y->second.dimInfo).get() == I)
             {
                 found = true;    
@@ -1256,4 +1374,5 @@
 int DataLogger::OpenRunFile(RunNumberType& run)
 {
+#ifdef RUN_LOGS
     if (run.logFile->is_open())
     {
@@ -1264,4 +1383,5 @@
     }
     FormRunTextFileName(run.logName, false, run.runNumber);
+    errno = 0;
     run.logFile->open(run.logName.c_str(), ios_base::out | ios_base::app);
     if (errno != 0)
@@ -1271,4 +1391,5 @@
         Error(str);
     }
+#endif
     //open report file
     FormRunTextFileName(run.reportName, true, run.runNumber);
@@ -1280,4 +1401,5 @@
         return -1;
     }
+    errno = 0;
     run.reportFile->open(run.reportName.c_str(), ios_base::out | ios_base::app);
     if (errno != 0)
@@ -1288,13 +1410,23 @@
     }
 
+#ifdef RUN_LOGS
     if (!run.logFile->is_open() || !run.reportFile->is_open())
+#else
+    if (!run.reportFile->is_open())
+#endif
     {
         ostringstream str;
-        str << "Something went wrong while openning nightly files " << run.logName << " and " << run.reportName;
+        str << "Something went wrong while openning files ";
+#ifdef RUN_LOGS
+        str << run.logName << " and ";
+#endif
+        str << run.reportName;
         Error(str);
         return -1;
     }
     //get the size of the newly opened file.
+#ifdef RUN_LOGS
     RememberFileOrigSizePlease(run.logName, false);
+#endif
     RememberFileOrigSizePlease(run.reportName, false);
 
@@ -1382,5 +1514,5 @@
         if (fakeFormat[fakeFormat.size()-1] == 'C')
             fakeFormat = fakeFormat.substr(0, fakeFormat.size()-1);
-        sub.fConv = new Converter(Out(), I->getFormat());    
+        sub.fConv = shared_ptr<Converter>(new Converter(Out(), I->getFormat()));
         if (!sub.fConv)
         {
@@ -1410,5 +1542,9 @@
                 cRunNumber = &(*rit);
                 sub.runNumber = rit->runNumber;
-                targetRunFile = isItaReport ? rit->reportFile : rit->logFile;
+#ifdef RUN_LOGS
+                targetRunFile = isItaReport ? (rit->reportFile).get() : (rit->logFile).get();
+#else
+                targetRunFile = isItaReport ? (rit->reportFile).get() : NULL;
+#endif
                 break;
             }
@@ -1536,20 +1672,16 @@
     if (fNightlyLogFile.is_open())
         Message("Nightly log-file: "/*+filename+*/" (OPEN)");
-    else
-        Message("Nightly log-file: "/*filename+*/" (CLOSED)");
+
     if (fNightlyReportFile.is_open())
         Message("Nightly report-file: "/*filename+*/" (OPEN)");
-    else
-        Message("Nightly report-file: "/*filename+*/" (CLOSED)");
+
     for (list<RunNumberType>::iterator it=fRunNumber.begin(); it!=fRunNumber.end(); it++)
     {
+#ifdef RUN_LOGS
         if (it->logFile->is_open())
             Message("Run log-file: " + it->logName + " (OPEN)");
-        else
-            Message("Run log-file: " + it->logName + " (CLOSED)");
+#endif
         if (it->reportFile->is_open())
             Message("Run report-file: " + it->reportName + " (OPEN)");
-        else
-            Message("Run report-file: " + it->reportName + " (CLOSED)");
     }
 
@@ -1728,5 +1860,11 @@
     if (evt.GetText() != NULL)
     {
-        fNightlyFilePath = string(evt.GetText());
+        string givenPath = string(evt.GetText());
+        if (!DoesPathExist(givenPath))
+        {
+            Error("Given Nightly folder \"" + givenPath + "\" does not exist. Please specify a valid path");
+            return GetCurrentState();
+        }
+        fNightlyFilePath = givenPath;
         Message("New Nightly folder specified: " + fNightlyFilePath);
     }
@@ -1747,5 +1885,11 @@
     if (evt.GetText() != NULL)
     {
-        fRunFilePath = string(evt.GetText());
+        string givenPath = string(evt.GetText());
+        if (!DoesPathExist(givenPath))
+        {
+            Error("Given Run folder \"" + givenPath + "\" does not exist. Please specify a valid path");
+            return GetCurrentState();
+        }
+        fRunFilePath = givenPath;
         Message("New Run folder specified: " + fRunFilePath);
     }
@@ -1933,5 +2077,5 @@
             try
             {
-                cRunNumber->runFitsFile = new CCfits::FITS(partialName, CCfits::RWmode::Write);
+                cRunNumber->runFitsFile = shared_ptr<CCfits::FITS>(new CCfits::FITS(partialName, CCfits::RWmode::Write));
                 (fNumSubAndFitsData.numOpenFits)++;
             }    
@@ -1941,5 +2085,5 @@
                 str << "Could not open FITS Run file " << partialName << " reason: " << e.message();
                 Error(str);
-                cRunNumber->runFitsFile = NULL;
+                cRunNumber->runFitsFile = shared_ptr<CCfits::FITS>();//NULL;
             }
 
@@ -1948,5 +2092,5 @@
         NotifyOpenedFile(baseFileName, 7, fOpenedRunFiles);// + '_' + serviceName, 4);
         if (hasGrouping)
-            sub.runFile.Open(partialName, serviceName, cRunNumber->runFitsFile, &fNumSubAndFitsData.numOpenFits, this, sub.runNumber);//Out());
+            sub.runFile.Open(partialName, serviceName, (cRunNumber->runFitsFile).get(), &fNumSubAndFitsData.numOpenFits, this, sub.runNumber);//Out());
         else
             sub.runFile.Open(partialName, serviceName, NULL, &fNumSubAndFitsData.numOpenFits, this, sub.runNumber);//Out());
@@ -2051,5 +2195,5 @@
         if (sub.nightlyFile.IsOpen())
         {
-            sub.nightlyFile.Write(sub.fConv);
+            sub.nightlyFile.Write(sub.fConv.get());
             if (fDebugIsOn)
             {
@@ -2059,5 +2203,5 @@
         if (sub.runFile.IsOpen())
         {
-            sub.runFile.Write(sub.fConv);
+            sub.runFile.Write(sub.fConv.get());
             if (fDebugIsOn)
             {
@@ -2163,5 +2307,7 @@
     const unsigned int n = 8 + 3 + 2*maxCharLength + 1; //+1 for trailling character
 
-    unsigned char* fitsBuffer = new unsigned char[n];
+    vector<unsigned char> realBuffer;
+    realBuffer.resize(n);
+    unsigned char* fitsBuffer = &realBuffer[0];
     memset(fitsBuffer, 0, n);
 
@@ -2218,7 +2364,13 @@
     for (list<RunNumberType>::iterator it=fRunNumber.begin(); it != fRunNumber.end(); it++)
     {
+#ifdef RUN_LOGS
         if (!it->logFile->is_open() || !it->reportFile->is_open())
+#else
+        if (!it->reportFile->is_open())
+#endif
             return kSM_FatalError;
+#ifdef RUN_LOGS
         it->logFile->close();
+#endif
         it->reportFile->close();
     }
