Index: /trunk/FACT++/src/dataLogger.cc
===================================================================
--- /trunk/FACT++/src/dataLogger.cc	(revision 10905)
+++ /trunk/FACT++/src/dataLogger.cc	(revision 10906)
@@ -182,5 +182,4 @@
             openedFits[fileName].push_back(serviceName);
     }
-
 };
 ///Dim subscription type. Stores all the relevant info to handle a Dim subscription
@@ -423,24 +422,8 @@
     ///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);
-    ///Form the name of the nightly text files (logs and reports)
-    void FormNightlyTextFileName(string& name, bool isReport);
-    ///Form the base (without extension) name of the run text files (logs and reports)
-    void FormBaseRunTextFileName(string& name, const int runNumber);
-    ///Form the name of the run text files (logs and reports)
-    void FormRunTextFileName(string& name, bool isReport, const int runNumber);
-    ///Form the name of the nightly Fits files
-    void FormNightlyFitsFileName(string& fileName, string& fileNameWithPath, const string& serviceName);
-    ///Form the name of the run Fits files
-    void FormRunFitsFileName(string& fileName, string& fileNameWithPath, const string& serviceName, const int runNumber);
-    ///Form the name of the grouped fits file (i.e. the file where several services are written)
-    void FormGroupedRunFitsFileName(string& fileName, string& fileNameWithPath, const int runNumber);
-    ///Form the name of the grouping fits file (i.e. the file that is created after a run ends)
-    void FormFitsGroupingFileName(string& fileNameWithPath, const int runNumber);
+    ///Form the files path
+    string CompileFileName(const string &path, const Time &time, const string &service, const string & extension);
+    ///Form the files path
+    string CompileFileName(const string &path, const Time &time, uint32_t run, const string &service, const string & extension);
     ///Check whether service is in black and/or white list
     bool ShouldSubscribe(const string& server, const string& service);
@@ -450,5 +433,5 @@
     void OpenTextFilePlease(ofstream& stream, const string& name);
     ///Check if a dir is . and returns the actual string corresponding to .
-    string CheckIfDirIsDot(const string& dir);
+//    string CheckIfDirIsDot(const string& dir);
     ///Remembers the size of newly opened files. for statistic purposes
     bool RememberFileOrigSizePlease(string& fileName, bool nightly);
@@ -457,4 +440,5 @@
     ///Checks if a given path exist
     bool DoesPathExist(string path);
+public:
     ///Create a given directory
     bool CreateDirectory(string path);
@@ -478,4 +462,30 @@
 bool DataLogger::CreateDirectory(string path)
 {
+    //remove last '/', if present
+    if (path[path.size()-1] == '/')
+        path = path.substr(0, path.size()-1);
+    //create boost path
+    boost::filesystem::path fullPath =  boost::filesystem::system_complete(boost::filesystem::path(path));
+
+    //if path does not exist, check if upper levels exist already
+    if (!boost::filesystem::exists(fullPath))
+    {
+        if (path.size() <= 1)
+        {//we're hitting "/", which SHOULD have existed...
+            Error("Something unexpected happened while creating a path");
+        }
+        CreateDirectory(path.substr(0, path.find_last_of('/')));
+    }
+    else
+    {//if path already exist, make sure it does not designate a file (filenames cannot be checked if they do not exist)
+        if (!boost::filesystem::is_directory(fullPath))
+        {
+            Error("Path to be created contains a file name: \"" + path + "\"");
+            return false;
+        }
+        else
+            return true;
+    }
+    //path does not exist, and upper level have been created already by recusrion.
     mode_t rightsMask = S_IRWXU | S_IXGRP | S_IRGRP | S_IXOTH | S_IROTH; //everybody read, owner writes
 
@@ -500,9 +510,23 @@
 bool DataLogger::DoesPathExist(string path)
 {
-    struct stat st;
-    if(stat(path.c_str(),&st) == 0)
-        return true;
-
-    return false;
+    boost::filesystem::path fullPath = boost::filesystem::system_complete(boost::filesystem::path(path));
+
+
+    if (!boost::filesystem::exists(fullPath))
+       return false;
+
+    if (!boost::filesystem::is_directory(fullPath))
+    {
+        Error("Path given for checking \"" + path + "\" designate a file name. Please provide a path name only");
+        return false;
+    }
+
+    if (access(path.c_str(), R_OK|W_OK|X_OK) != 0)
+    {
+        Error("Missing read, write or execute permissions on directory\"" + path + "\"");
+        return false;
+    }
+
+    return true;
 }
 // --------------------------------------------------------------------------
@@ -603,32 +627,5 @@
     return false;
 }
-// --------------------------------------------------------------------------
-//
-//! Checks if a given directory is simply '.' and retrieves the coresponding full path
-//! @param dir the input directory that should be checked against
-//! @return the full path corresponding to the input directory
-//
-string DataLogger::CheckIfDirIsDot(const string& dir)
-{
-    errno = 0;
-    if (dir == ".")
-    {
-        char currentPath[FILENAME_MAX];
-        if (!getcwd(currentPath, sizeof(currentPath)))
-        {
-            if (errno != 0)
-            {
-                ostringstream str;
-                str << "Unable to retrieve the current path" << ". Reason: " << strerror(errno) << " [" << errno << "]";
-                Error(str);
-            }
-        }
-        return string(currentPath);
-    }
-    else
-    {
-        return string(dir);
-    }
-}
+
 // --------------------------------------------------------------------------
 //
@@ -687,260 +684,68 @@
 // --------------------------------------------------------------------------
 //
-//!Form the name of the grouped fits file (i.e. the file where several services are written)
-//! @param fileName only the file name itself (no path)
-//! @param fileNameWithPath fileName, augmented with the prefix path
-//! @param runNumber the current run number for which the file should be opened.
-//
-void DataLogger::FormGroupedRunFitsFileName(string& fileName, string& fileNameWithPath, const int runNumber)
-{
-    ostringstream sRun;
-    sRun << runNumber;
-    fileName = sRun.str() + "_group.fits";
-    string path;
-    FormBaseRunPath(path, runNumber);
-    fileNameWithPath = path + '/' + fileName;
-}
-
-// --------------------------------------------------------------------------
-//
-//! Form the name of the grouping fits file (i.e. the file that is created after a run ends)
-//! This file is meant to link the various fits files related to a particular run from a single file
-//! @param fileNameWithPath the full filename
-//! @param runNumber the current run number for which the file should be opened. -1 means nightly grouping
-//
-void DataLogger::FormFitsGroupingFileName(string& fileNameWithPath, const int runNumber)
-{
-    ostringstream groupName;
-    string path;
-    if (runNumber != 0)
-    {
-        FormBaseRunPath(path, runNumber);
-        groupName << path << '/' << runNumber << ".fits";
-    }
-    else
-    {
-        ostringstream sTime;
-        unsigned short year, month, day;
-        GetYearMonthDayForFiles(year, month, day);
-        sTime << year << "_" << month << "_" << day;
-        FormBaseNightlyPath(path);
-
-        groupName << path << '/' << sTime.str() << ".fits";
-    }
-    fileNameWithPath = groupName.str();
-
-}
-// --------------------------------------------------------------------------
-//
-//! Form the name of the nightly Fits files
-//! @param fileName the file name only
-//! @param fileNameWithPath the fileName augmented by the prefix path
-//! @param serviceName the service for which this file should be opened
-//
-void DataLogger::FormNightlyFitsFileName(string& fileName, string& fileNameWithPath, const string& serviceName)
-{
-    ostringstream sTime;
-    unsigned short year, month, day;
-    GetYearMonthDayForFiles(year, month, day);
-    sTime << year << "_" << month << "_" << day;
-    fileName = sTime.str() + '_' + serviceName + ".fits";
-    string path;
-    FormBaseNightlyPath(path);
-    fileNameWithPath = path + '/' + fileName;
-}
-// --------------------------------------------------------------------------
-//
-//! Form the name of the run Fits files
-//! @param fileName the file name only
-//! @param fileNameWithPath the fileName augmented by the prefix path
-//! @param serviceName the service for which this file should be opened
-//! @param runNumber the current run number for which this file should be opened
-//
-void DataLogger::FormRunFitsFileName(string& fileName, string& fileNameWithPath, const string& serviceName, const int runNumber)
-{
-    ostringstream sRun;
-    sRun << runNumber;
-    fileName = sRun.str() + '_' + serviceName + ".fits";
-    string path;
-    FormBaseRunPath(path, runNumber);
-    fileNameWithPath = path + '/' + fileName;
-}
-// --------------------------------------------------------------------------
-//
-//! Form the base (without extension) name of the run text files (logs and reports)
-//! @param name the full file name
-//! @param runNumber the current run number for which this file should be opened
-//
-void DataLogger::FormBaseRunTextFileName(string& name, const int runNumber)
-{
-    ostringstream sRun;
-    sRun << runNumber;
-    string path;
-    FormBaseRunPath(path, runNumber);
-    name = path + '/' + sRun.str();
-}
-// --------------------------------------------------------------------------
-//
-//! Form the name of the run text files (logs and reports)
-//! @param name the full file name
-//! @param isReport whether a log or report name should be formed
-//! @param runNumber the current run number for which this file should be opened
-//
-void DataLogger::FormRunTextFileName(string& name, bool isReport, const int runNumber)
-{
-    FormBaseRunTextFileName(name, runNumber);
-
-    if (isReport)
-        name += ".rep";
-    else
-        name += ".log";
-}
-// --------------------------------------------------------------------------
-//
-//! Form the base (without extension) name of the nightly text files (logs and reports)
-//! @param name the full file name
-//
-void DataLogger::FormBaseNightlyTextFileName(string& name)
-{
-    ostringstream sTime;
-    unsigned short year, month, day;
-    GetYearMonthDayForFiles(year, month, day);
-    sTime << year << "_" << month << "_" << day;
-
-    FormBaseNightlyPath(name);
-
-    name += '/' + sTime.str();
-}
-// --------------------------------------------------------------------------
-//
-//! Form the name of the nightly text files (logs and reports)
-//! @param name the full file name
-//! @param isReport whether a log or report name should be formed
-//
-void DataLogger::FormNightlyTextFileName(string& name, bool isReport)
-{
-    FormBaseNightlyTextFileName(name);
-
-    if (isReport)
-        name += ".rep";
-    else
-        name += ".log";
-}
-// --------------------------------------------------------------------------
-//
-//!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();
-}
+//! Compiles a file name
+//! @param path the base path where to put the file
+//! @param time the time at which the file is created
+//! @param service the service name, if any
+//! @param extension the extension to add, if any
+//
+string DataLogger::CompileFileName(const string &path, const Time &time, const string &service, const string & extension)
+{
+       ostringstream str;
+       //calculate time suitable for naming files.
+       Time fTime(time-boost::posix_time::time_duration(12,0,0));
+
+       //output it
+       str << path << Time::fmt("/%Y/%m/%d") << fTime;
+
+       //check if target directory exist
+       if (!DoesPathExist(str.str()))
+           CreateDirectory(str.str());
+
+       //output base of file name
+       str << Time::fmt("/%Y_%m_%d") << fTime;
+
+       //output service name
+       if (!service.empty())
+           str  << "_" << service;
+
+       //output appropriate extension
+       if (!extension.empty())
+           str << "." << extension;
+
+       return str.str();
+}
+// --------------------------------------------------------------------------
+//
+//! Compiles a file name
+//! @param path the base path where to put the file
+//! @param time the time at which the file is created
+//! @param run the run number
+//! @param service the service name, if any
+//! @param extension the extension to add, if any
+//
+string DataLogger::CompileFileName(const string &path, const Time &time, uint32_t run, const string &service, const string & extension)
+{
+       ostringstream str;
+       //calculate suitable time for naming files and output it
+       str << path << Time::fmt("/%Y/%m/%d") << (time-boost::posix_time::time_duration(12,0,0));
+
+       //check if target directory exist
+       if (!DoesPathExist(str.str()))
+           CreateDirectory(str.str());
+
+       //output base of file name
+       str << '/' << setfill('0') << setw(8) << run;
+
+       //output service name
+       if (!service.empty())
+           str  << "_" << service;
+
+       //output appropriate extension
+       if (!extension.empty())
+           str << "." << extension;
+       return str.str();
+}
+
 // --------------------------------------------------------------------------
 //
@@ -1382,5 +1187,5 @@
         return -1;
     }
-    FormRunTextFileName(run.logName, false, run.runNumber);
+    run.logName = CompileFileName(fRunFilePath, Time(), run.runNumber, "", "log");
     errno = 0;
     run.logFile->open(run.logName.c_str(), ios_base::out | ios_base::app);
@@ -1393,5 +1198,5 @@
 #endif
     //open report file
-    FormRunTextFileName(run.reportName, true, run.runNumber);
+    run.reportName = CompileFileName(fRunFilePath, Time(), run.runNumber, "", "rep");
     if (run.reportFile->is_open())
     {
@@ -1432,6 +1237,5 @@
 
     //TODO this notification scheme might be messed up now.... fix it !
-    string baseFileName;
-    FormBaseRunTextFileName(baseFileName, run.runNumber);
+    string baseFileName = CompileFileName(fRunFilePath, Time(), run.runNumber, "", "");
     NotifyOpenedFile(baseFileName, 3, fOpenedRunFiles);
     run.openedFits.clear();
@@ -1658,6 +1462,6 @@
 
     //print the path configuration
-    Message("Nightly Path: " + CheckIfDirIsDot(fNightlyFilePath));
-    Message("Run Path: " + CheckIfDirIsDot(fRunFilePath));
+    Message("Nightly Path: " + boost::filesystem::system_complete(boost::filesystem::path(fNightlyFilePath)).directory_string());
+    Message("Run Path: " + boost::filesystem::system_complete(boost::filesystem::path(fRunFilePath)).directory_string());
 
     //print active run numbers
@@ -1863,5 +1667,5 @@
         if (!DoesPathExist(givenPath))
         {
-            Error("Given Nightly folder \"" + givenPath + "\" does not exist. Please specify a valid path");
+            Error("Provided path is not a valid folder. Ignored");
             return GetCurrentState();
         }
@@ -1888,5 +1692,5 @@
         if (!DoesPathExist(givenPath))
         {
-            Error("Given Run folder \"" + givenPath + "\" does not exist. Please specify a valid path");
+            Error("Provided path is not a valid folder. Ignored");
             return GetCurrentState();
         }
@@ -1957,9 +1761,8 @@
         Debug("Starting...");    
     }
-
-    FormNightlyTextFileName(fFullNightlyLogFileName, false);
+    fFullNightlyLogFileName = CompileFileName(fNightlyFilePath, Time(), "", "log");
     OpenTextFilePlease(fNightlyLogFile, fFullNightlyLogFileName);
 
-    FormNightlyTextFileName(fFullNightlyReportFileName, true);
+    fFullNightlyReportFileName = CompileFileName(fNightlyFilePath, Time(), "", "rep");
     OpenTextFilePlease(fNightlyReportFile, fFullNightlyReportFileName);
 
@@ -1979,6 +1782,5 @@
 
     //notify that a new file has been opened.
-    string baseFileName;
-    FormBaseNightlyTextFileName(baseFileName);
+    string baseFileName = CompileFileName(fNightlyFilePath, Time(), "", "");
     NotifyOpenedFile(baseFileName, 3, fOpenedNightlyFiles);
 
@@ -2030,5 +1832,6 @@
     {
         string fileNameOnly, partialName;
-        FormNightlyFitsFileName(fileNameOnly, partialName, serviceName);
+        partialName = CompileFileName(fNightlyFilePath, Time(), serviceName, "fits");
+        fileNameOnly = partialName.substr(partialName.find_last_of('/')+1, partialName.size());
         AllocateFITSBuffers(sub);
         //get the size of the file we're about to open
@@ -2039,6 +1842,5 @@
 
         //notify the opening
-        string baseFileName;
-        FormBaseNightlyTextFileName(baseFileName);
+        string baseFileName = CompileFileName(fNightlyFilePath, Time(), "", "");
         NotifyOpenedFile(baseFileName, 7, fOpenedNightlyFiles);
         if (fNumSubAndFitsIsOn)
@@ -2056,12 +1858,13 @@
         string fileNameOnly;
         string partialName;
-
         if (hasGrouping)
         {
-            FormGroupedRunFitsFileName(fileNameOnly, partialName, sub.runNumber);
+            partialName = CompileFileName(fRunFilePath, Time(), sub.runNumber, "group", "fits");
+            fileNameOnly = partialName.substr(partialName.find_last_of('/')+1, partialName.size());
         }
         else
         {
-            FormRunFitsFileName(fileNameOnly, partialName, serviceName, sub.runNumber);
+            partialName = CompileFileName(fRunFilePath, Time(), sub.runNumber, serviceName, "fits");
+            fileNameOnly = partialName.substr(partialName.find_last_of('/')+1, partialName.size());
         }
         //get the size of the file we're about to open
@@ -2088,6 +1891,5 @@
             }
 
-        string baseFileName;
-        FormBaseRunTextFileName(baseFileName, sub.runNumber);
+        string baseFileName = CompileFileName(fRunFilePath, Time(), sub.runNumber, "", "");
         NotifyOpenedFile(baseFileName, 7, fOpenedRunFiles);// + '_' + serviceName, 4);
         if (hasGrouping)
@@ -2269,6 +2071,5 @@
         return;
     }
-    string groupName;
-    FormFitsGroupingFileName(groupName, runNumber);
+    string groupName = CompileFileName(fRunFilePath, Time(), runNumber, "", "fits");
     CCfits::Table* groupTable;
     int maxCharLength = 50;//FILENAME_MAX;
@@ -2532,4 +2333,5 @@
 
     DataLogger logger(wout);
+
     if (!logger.SetConfiguration(conf))
         return -1;
