Index: trunk/FACT++/src/Fits.cc
===================================================================
--- trunk/FACT++/src/Fits.cc	(revision 11218)
+++ trunk/FACT++/src/Fits.cc	(revision 11219)
@@ -342,8 +342,10 @@
 //			if (fTable != NULL)
 //				delete fTable;
-
-	WriteSingleHeaderKey("TSTOP", fEndMjD, "Time of the last receied data");
+    fMess->Info("Closing: "+fFileName);
 	if (fFile != NULL && fOwner)
 	{
+//	    CCfits::FITS* backupFits = fFile;
+//	    fFile = NULL;
+	    WriteSingleHeaderKey("TSTOP", fEndMjD, "Time of the last receied data");
 //	    fFile->flush();
 	    delete fFile;
Index: trunk/FACT++/src/datalogger.cc
===================================================================
--- trunk/FACT++/src/datalogger.cc	(revision 11218)
+++ trunk/FACT++/src/datalogger.cc	(revision 11219)
@@ -63,5 +63,4 @@
 
 #include <fstream>
-#include <mutex>
 
 #include <boost/bind.hpp>
@@ -199,5 +198,6 @@
         kSM_BadNightlyConfig = 0x101, ///< the folder specified for Nightly logging does not exist or has bad permissions
         kSM_BadRunConfig = 0x102, ///<  the folder specified for the run logging does not exist or has wrong permissions or no run number
-        kSM_WriteError = 0x103, ///< Denotes that an error occured while writing a file (text or fits).
+        kSM_RunWriteError = 0x103, ///< Denotes that an error occured while writing a run file (text or fits).
+        kSM_DailyWriteError = 0x103,///< Denots that an error occured while writing a daily file (text or fits).
     } localstates_t;
     
@@ -297,10 +297,4 @@
     ///variables for computing statistics
     DataLoggerStats fStatVar;
-    ///mutex to make sure that the Stats are not accessed while updating
-//    mutex fStatsMutex;
-    ///services notification thread
-//    boost::thread fMonitoringThread;
-    ///end of the monitoring
-//    bool fContinueMonitoring;
     ///stores the size of each file that is or was open
     map<string, long> fFileSizesMap;
@@ -353,4 +347,5 @@
     ///add a new run number
     void AddNewRunNumber(int64_t newRun, Time time);
+    std::vector<int64_t> previousRunNumbers;
     ///removes the oldest run number, and close the relevant files.
     void RemoveOldestRunNumber();
@@ -380,7 +375,8 @@
     bool RememberFileOrigSizePlease(string& fileName, bool nightly);
     ///Checks if the input osftream is in error state, and if so close it.
-    bool CheckForOfstreamError(ofstream& out);
-    ///Goes to Write error state and also closes all opened files
-    void GoToWriteErrorState();
+    bool CheckForOfstreamError(ofstream& out, bool isDailyStream);
+    ///Goes to Write error states
+    void GoToRunWriteErrorState();
+    void GoToNightlyWriteErrorState();
     ///Checks if a given path exist
     bool DoesPathExist(string path);
@@ -556,5 +552,5 @@
 //! @param out the ofstream that should be checked
 //
-bool DataLogger::CheckForOfstreamError(ofstream& out)
+bool DataLogger::CheckForOfstreamError(ofstream& out, bool isDailyStream)
 {
     if (out.good())
@@ -562,10 +558,12 @@
 
     Error("An error occured while writing to a text file. Closing it");
-//    if (out.is_open())
-//        out.close();
-    GoToWriteErrorState();
+    if (out.is_open())
+        out.close();
+    if (isDailyStream)
+        GoToNightlyWriteErrorState();
+    else
+        GoToRunWriteErrorState();
 
     return false;
-//    SetCurrentState(kSM_WriteError);
 }
 // --------------------------------------------------------------------------
@@ -700,4 +698,26 @@
 //
 //! Compiles a file name
+//! @param run the run number
+//! @param service the service name, if any
+//! @param extension the extension to add, if any
+//
+string DataLogger::CompileFileName(const uint32_t run, const string& service, const string& extension)
+{
+       ostringstream 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();
+}
+// --------------------------------------------------------------------------
+//
+//! Compiles a file name withh path
 //! @param path the base path where to put the file
 //! @param time the time at which the file is created
@@ -706,21 +726,4 @@
 //! @param extension the extension to add, if any
 //
-//string DataLogger::CompileFileName(const string &path, uint32_t run, const string &service, const string & extension, const Time &time)
-string DataLogger::CompileFileName(const uint32_t run, const string& service, const string& extension)//, const Time& time)
-{
-       ostringstream 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();
-}
-
 string DataLogger::CompileFileNameWithPath(const string& path, const uint32_t run, const string& service, const string& extension, const Time& time)
 {
@@ -783,6 +786,4 @@
             {
                 y->second.runFile.Close();
-
-                Info("Closed: "+y->second.runFile.fFileName);
             }
     //if a grouping file is on, decrease the number of opened fits manually
@@ -802,7 +803,4 @@
 bool DataLogger::calculateTotalSizeWritten(DataLoggerStats& statVar, bool isPrinting)
 {
-//mutex
-//    if (!isPrinting)
-//        fStatsMutex.lock();
 #ifdef HAVE_FITS
     if (isPrinting)
@@ -872,58 +870,7 @@
     statVar.sizeWritten -= fBaseSizeRun;
 
-//mutex
-//    if (!isPrinting)
-//        fStatsMutex.unlock();
-
     return shouldWarn;
 }
 
-// --------------------------------------------------------------------------
-//
-//! Monitor the number of opened files and total size written, and distributes this data through a Dim service
-//
-//
-/*
-void DataLogger::ServicesMonitoring()
-{
-       struct statvfs vfs;
-        if (!statvfs(fNightlyFilePath.c_str(), &vfs))
-            fStatVar.freeSpace = vfs.f_bsize*vfs.f_bavail;
-        else
-            fStatVar.freeSpace = -1;
-
-        DimDescribedService srvc ("DATA_LOGGER/STATS", "X:3", fStatVar, "Add description here");
-        fPreviousSize = 0;
-        //loop-wait for broadcast
-        while (fContinueMonitoring)
-        {
-            if (fStatsPeriodDuration == 0.0f)
-            {
-                sleep(0.1f);
-                continue;
-            }
-
-            sleep(fStatsPeriodDuration);
-
-
-            fStatsMutex.lock();
-
-            if (fStatVar.writingRate != 0) //if data has been written
-            {
-                srvc.updateService();
-
-                if(fDebugIsOn)
-                {
-                    ostringstream str;
-                    str << "Size written: " << fStatVar.sizeWritten/1000 << " kB; writing rate: ";
-                    str << fStatVar.writingRate/1000 << " kB/s; free space: ";
-                    str << fStatVar.freeSpace/(1000*1000) << " MB";
-                    Debug(str);
-                }
-            }
-            fStatsMutex.unlock();
-        }
-}
-*/
 // --------------------------------------------------------------------------
 //
@@ -945,5 +892,6 @@
     AddStateName(kSM_BadNightlyConfig, "ErrNightlyFolder", "The folder for the nighly summary files is invalid.");
     AddStateName(kSM_BadRunConfig,     "ErrRunFolder",     "The folder for the run files is invalid.");
-    AddStateName(kSM_WriteError,       "ErrWrite",          "An error occured while writing to a file.");
+    AddStateName(kSM_DailyWriteError,  "ErrDailyWrite",    "An error occured while writing to a daily (and run) file.");
+    AddStateName(kSM_RunWriteError,    "ErrRunWrite",      "An error occured while writing to a run file.");
 
     // Add the possible transitions for this machine
@@ -952,5 +900,5 @@
         ("Start the nightly logging. Nightly file location must be specified already");
 
-    AddEvent(kSM_Ready, "STOP", kSM_NightlyOpen, kSM_WaitingRun, kSM_Logging, kSM_WriteError)
+    AddEvent(kSM_Ready, "STOP", kSM_NightlyOpen, kSM_WaitingRun, kSM_Logging, kSM_DailyWriteError, kSM_RunWriteError)
         (boost::bind(&DataLogger::GoToReadyPlease, this))
         ("Stop all data logging, close all files.");
@@ -964,5 +912,5 @@
         ("Wait for a run to be started, open run-files as soon as a run number arrives.");
 
-    AddEvent(kSM_Ready, "RESET", kSM_Error, kSM_BadNightlyConfig, kSM_BadRunConfig, kSM_WriteError)
+    AddEvent(kSM_Ready, "RESET", kSM_Error, kSM_BadNightlyConfig, kSM_BadRunConfig, kSM_DailyWriteError, kSM_RunWriteError)
         (boost::bind(&DataLogger::GoToReadyPlease, this))
         ("Transition to exit error states. Closes the any open file.");
@@ -1020,7 +968,7 @@
 
      // provide services control commands
-     AddEvent("SET_DEUG_MODE", "B:1", kSM_NightlyOpen, kSM_Logging, kSM_WaitingRun, kSM_Ready)
+     AddEvent("SET_DEBUG_MODE", "B:1", kSM_NightlyOpen, kSM_Logging, kSM_WaitingRun, kSM_Ready)
          (boost::bind(&DataLogger::SetDebugOnOff, this, _1))
-         ("Switch debug mode on or off. Debug mode prints ifnormation about every service written to a file."
+         ("Switch debug mode on or off. Debug mode prints information about every service written to a file."
           "|Enable[bool]:Enable of disable debug mode (yes/no).");
 
@@ -1063,7 +1011,4 @@
      fStatsMonitoring = new DimDescribedService(GetName() + "/STATS", "X:3", fStatVar, "Add description here");
 
-//mutex
-//     fContinueMonitoring = true;
-//     fMonitoringThread = boost::thread(boost::bind(&DataLogger::ServicesMonitoring, this));
      fBaseSizeNightly = 0;
      fBaseSizeRun = 0;
@@ -1089,16 +1034,14 @@
     //first let's go to the ready state
     GoToReadyPlease(); 
+    dim_lock();
     //release the services subscriptions
     fServiceSubscriptions.clear();
-    //exit the monitoring loop
-//mutex
-//    fContinueMonitoring = false;
-//    fMonitoringThread.join();
+
     //clear any remaining run number (should remain only one)
-     while (fRunNumber.size() > 0)
+    while (fRunNumber.size() > 0)
      {
          RemoveOldestRunNumber();
      }
-
+    dim_unlock();
     delete fOpenedNightlyFiles;
     delete fOpenedRunFiles;
@@ -1169,4 +1112,8 @@
     if (I==NULL)
         return;
+
+    //it may happen that we try to write a dimInfo while closing files. Prevent that with a dim_lock()
+    dim_lock();
+
     //check if the service pointer corresponds to something that we subscribed to
     //this is a fix for a bug that provides bad Infos when a server starts
@@ -1174,5 +1121,5 @@
     SubscriptionsListType::iterator x;
     map<string, SubscriptionType>::iterator y;
-     for (x=fServiceSubscriptions.begin(); x != fServiceSubscriptions.end(); x++)
+    for (x=fServiceSubscriptions.begin(); x != fServiceSubscriptions.end(); x++)
     {//find current service is subscriptions
         for (y=x->second.begin(); y!=x->second.end();y++)
@@ -1188,15 +1135,20 @@
     {
         DimServiceInfoList::infoHandler();
+        dim_unlock();
         return;
     }
     if (I->getSize() <= 0 || I->getData()==NULL)
+    {
+        dim_unlock();
         return;
-
+    }
         // Make sure that getTimestampMillisecs is NEVER called before
         // getTimestamp is properly called
         // check that the message has been updated by something, i.e. must be different from its initial value
     if (I->getTimestamp() == 0)
+    {
+        dim_unlock();
         return;
-
+    }
     // FIXME: Here we have to check if we have received the
     //        service with the run-number.
@@ -1207,4 +1159,5 @@
     ReportPlease(I, y->second);
 
+    dim_unlock();
     //update the fits files sizes
     UpdateStatisticsService();
@@ -1292,4 +1245,13 @@
         return;
     }
+    for (std::vector<int64_t>::const_iterator it=previousRunNumbers.begin(); it != previousRunNumbers.end(); it++)
+    {
+        if (*it == newRun)
+        {
+            Error("Newly provided run number has already been used (or is still in use). Going to error state");
+            SetCurrentState(kSM_BadRunConfig);
+            return;
+        }
+    }
     if (fDebugIsOn)
     {
@@ -1315,8 +1277,14 @@
         {
             if (it->reportFile->is_open())
+            {
                 it->reportFile->close();
+                Info("Closing: "+it->reportName);
+            }
 #ifdef RUN_LOGS
             if (it->logFile->is_open())
+            {
                 it->logFile->close();
+                Info("Closing: "+it->logName);
+            }
 #endif
         }
@@ -1496,5 +1464,5 @@
         {
             fNightlyReportFile << header.str() << text << endl;
-            if (!CheckForOfstreamError(fNightlyReportFile))
+            if (!CheckForOfstreamError(fNightlyReportFile, true))
                 return;
         }
@@ -1503,5 +1471,5 @@
         {
             *targetRunFile << header.str() << text << endl;
-            if (!CheckForOfstreamError(*targetRunFile))
+            if (!CheckForOfstreamError(*targetRunFile, false))
                 return;
         }
@@ -1515,5 +1483,5 @@
         {
             MessageImp(fNightlyLogFile).Write(cTime, msg.str().c_str(), fQuality);
-            if (!CheckForOfstreamError(fNightlyLogFile))
+            if (!CheckForOfstreamError(fNightlyLogFile, true))
                 return;
         }
@@ -1521,5 +1489,5 @@
         {
             MessageImp(*targetRunFile).Write(cTime, msg.str().c_str(), fQuality);
-            if (!CheckForOfstreamError(*targetRunFile))
+            if (!CheckForOfstreamError(*targetRunFile, false))
                 return;
         }
@@ -1788,4 +1756,16 @@
 }
 
+// --------------------------------------------------------------------------
+//
+//!    Configure a given file name
+//! @param target
+//!        where to put the result
+//! @param type
+//!         what to append to the created path. currently only run or nightly
+//! @param evt
+//!         the event transporting the path
+//! @returns
+//!        currently only the current state.
+//
 int DataLogger::ConfigureFileName(string &target, const string &type, const EventImp &evt)
 {
@@ -1906,4 +1886,5 @@
     {
         fNightlyLogFile.close();
+        Info("Closed: "+fFullNightlyReportFileName);
         return kSM_BadNightlyConfig;
     }
@@ -1980,5 +1961,5 @@
         if (!sub.nightlyFile.Open(partialName, serviceName, NULL, &fNumSubAndFitsData.numOpenFits, this, 0))
         {
-            GoToWriteErrorState();
+            GoToRunWriteErrorState();
             //SetCurrentState(kSM_WriteError);
             return;
@@ -2026,5 +2007,5 @@
                 Error(str);
                 cRunNumber->runFitsFile = shared_ptr<CCfits::FITS>();//NULL;
-                GoToWriteErrorState();
+                GoToRunWriteErrorState();
                 //SetCurrentState(kSM_WriteError);
                 return;
@@ -2042,5 +2023,5 @@
             if (!sub.runFile.Open(partialName, serviceName, (cRunNumber->runFitsFile).get(), &fNumSubAndFitsData.numOpenFits, this, sub.runNumber))
             {
-                GoToWriteErrorState();
+                GoToRunWriteErrorState();
                 //SetCurrentState(kSM_WriteError);
                 return;
@@ -2049,7 +2030,7 @@
         else
         {
-            if (sub.runFile.Open(partialName, serviceName, NULL, &fNumSubAndFitsData.numOpenFits, this, sub.runNumber))
+            if (!sub.runFile.Open(partialName, serviceName, NULL, &fNumSubAndFitsData.numOpenFits, this, sub.runNumber))
             {
-                GoToWriteErrorState();
+                GoToRunWriteErrorState();
                 //SetCurrentState(kSM_WriteError);
                 return;
@@ -2096,5 +2077,5 @@
          switch (flist[i].first.first->name()[0])
          {
-         case 'c': dataQualifier << "B"; break; // FIXME: To be checked!
+         case 'c': dataQualifier << "S"; break;
          case 's': dataQualifier << "I"; break;
          case 'i': dataQualifier << "J"; break;
@@ -2128,5 +2109,6 @@
             if (!sub.nightlyFile.Write(sub.fConv.get()))
             {
-                GoToWriteErrorState();
+                sub.nightlyFile.Close();
+                GoToNightlyWriteErrorState();
                 return;
               //SetCurrentState(kSM_WriteError);
@@ -2138,5 +2120,6 @@
             if (!sub.runFile.Write(sub.fConv.get()))
             {
-                GoToWriteErrorState();
+                sub.runFile.Close();
+                GoToRunWriteErrorState();
                 return;
                 //SetCurrentState(kSM_WriteError);
@@ -2145,11 +2128,23 @@
 }
 #endif //if has_fits
-
-void DataLogger::GoToWriteErrorState()
-{
-    GoToReadyPlease();
-    SetCurrentState(kSM_WriteError);
-}
-
+// --------------------------------------------------------------------------
+//
+//! Go to Run Write Error State
+//      A write error has occurred. Checks what is the current state and take appropriate action
+void DataLogger::GoToRunWriteErrorState()
+{
+    if ((GetCurrentState() != kSM_RunWriteError) &&
+        (GetCurrentState() != kSM_DailyWriteError))
+        SetCurrentState(kSM_RunWriteError);
+}
+// --------------------------------------------------------------------------
+//
+//! Go to Nightly Write Error State
+//      A write error has occurred. Checks what is the current state and take appropriate action
+void DataLogger::GoToNightlyWriteErrorState()
+{
+    if (GetCurrentState() != kSM_DailyWriteError)
+        SetCurrentState(kSM_DailyWriteError);
+}
 std::string DataLogger::SetCurrentState(int state, const char *txt, const std::string &cmd)
 {
@@ -2309,5 +2304,6 @@
                 str << "Writing FITS row " << i << " in " << groupName << ": " << text << " (file_write_tblbytes, rc=" << status << ")";
                 Error(str);
-                GoToWriteErrorState();
+                GoToRunWriteErrorState();
+                delete groupFile;
                 return;
             }
@@ -2332,4 +2328,7 @@
         Debug("Stopping Run Logging...");    
     }
+    //it may be that dim tries to write a dimInfo at the same time as we're closing files. Prevent this
+
+    dim_lock();
     for (list<RunNumberType>::const_iterator it=fRunNumber.begin(); it != fRunNumber.end(); it++)
     {
@@ -2342,6 +2341,9 @@
 #ifdef RUN_LOGS
         it->logFile->close();
+        Info("Closed: "+it->logName);
+
 #endif
         it->reportFile->close();
+        Info("Closed: "+it->reportName);
     }
 
@@ -2362,5 +2364,5 @@
         RemoveOldestRunNumber();
     }
-
+    dim_unlock();
     return kSM_WaitingRun;
 }
@@ -2379,10 +2381,17 @@
    if (GetCurrentState() == kSM_Logging)
        StopRunPlease();
-
+   //it may be that dim tries to write a dimInfo while we're closing files. Prevent that
+   dim_lock();
+   const string baseFileName = CompileFileNameWithPath(fNightlyFilePath, "", "");
     if (fNightlyLogFile.is_open())
+    {
         fNightlyLogFile.close();
+        Info("Closed: "+baseFileName+".log");
+    }
     if (fNightlyReportFile.is_open())
+    {
         fNightlyReportFile.close();
-        
+        Info("Closed: "+baseFileName+".rep");
+    }
 #ifdef HAVE_FITS
     for (SubscriptionsListType::iterator i = fServiceSubscriptions.begin(); i != fServiceSubscriptions.end(); i++)
@@ -2390,5 +2399,5 @@
         {
             if (j->second.nightlyFile.IsOpen())
-                j->second.nightlyFile.Close();;
+                j->second.nightlyFile.Close();
         }
 #endif
@@ -2404,4 +2413,5 @@
     CreateFitsGrouping(fOpenedNightlyFits, 0);
 #endif
+    dim_unlock();
     return kSM_Ready;
 }
