Index: trunk/FACT++/src/FilesStatisticsService.cc
===================================================================
--- trunk/FACT++/src/FilesStatisticsService.cc	(revision 11292)
+++ trunk/FACT++/src/FilesStatisticsService.cc	(revision 11304)
@@ -1,14 +1,19 @@
+//*************************************************************************************
+/** @class DimWriteStatistics
+
+ @brief provides a statistics service telling the free space on disk and the total size written so far
+
+*/
+//*************************************************************************************
 #include "FilesStatisticsService.h"
+
 #include <sys/statvfs.h> //for getting disk free space
 #include <sys/stat.h>    //for getting files sizes
+
 #include "Time.h"
-// --------------------------------------------------------------------------
-//
-//! Default constructor. Should NOT be used otherwise the service name will be wrong
-//
-//FilesStatisticsService::FilesStatisticsService()
-//{
- //   FilesStatisticsService("YouDidntCallTheProperConstructor");
-//}
+
+using namespace std;
+using namespace boost::posix_time;
+
 // --------------------------------------------------------------------------
 //
@@ -17,29 +22,34 @@
 //! @param serverName the name of the server which created this object
 //
-FilesStatisticsService::FilesStatisticsService(const string& serverName, MessageImp* mess) : fServerName(serverName),
-                                                                                             fCurrentFolder("."),
-                                                                                             fContinueStats(true),
-                                                                                             fDebug(false),
-                                                                                             fBaseSize(0),
-                                                                                             fPeriodDuration(1),
-                                                                                             fMess(mess)
-{
-    fStats.sizeWritten = 0;
-    fStats.freeSpace = 0;
-    fStats.writingRate = 0;
-    fService = new DimDescribedService(serverName + "/STATS", "X:3", fStats, "Statistics about size written");
-    fThread = boost::thread(boost::bind(&FilesStatisticsService::UpdateService, this));
-}
-// --------------------------------------------------------------------------
-//
-//! Default destructor.
-//
-FilesStatisticsService::~FilesStatisticsService()
-{
-    fContinueStats = false;
-//WARNING: DO NOT DO JOIN OTHERWISE THE DESTRUCTOR BLOCKS
-//    fThread.join();
-    delete fService;
-}
+DimWriteStatistics::DimWriteStatistics(const string& server, MessageImp &log) :
+    fLog(log),
+    fDimService(server + "/STATS",  "X:4", "Statistics about size written"),
+    fCurrentFolder("."),
+    fUpdateInterval(1000),
+    fBaseSize(0),
+    fDebug(false)
+{
+    fThread = boost::thread(boost::bind(&DimWriteStatistics::UpdateService, this));
+}
+
+// --------------------------------------------------------------------------
+//
+//! Destructor. Stop thread by setting fUpdateInterval to 0 and join the
+//! thread.
+//
+DimWriteStatistics::~DimWriteStatistics()
+{
+    fUpdateInterval = 0;
+
+    // This blocks for fPeriod duration, but maybe canceling the thread
+    // could be more dangerous leaving Dim in an undefined state.
+    fThread.interrupt();
+}
+
+int DimWriteStatistics::Write(const Time &t, const string &txt, int qos)
+{
+    return fLog.Write(t, txt, qos);
+}
+
 // --------------------------------------------------------------------------
 //
@@ -47,11 +57,13 @@
 //! @return the available free space on disk, in bytes
 //
-long FilesStatisticsService::GetFreeSpace()
+int64_t DimWriteStatistics::GetFreeSpace()
 {
     struct statvfs vfs;
     if (statvfs(fCurrentFolder.c_str(), &vfs))
         return -1;
+
     return vfs.f_bsize*vfs.f_bavail;
 }
+
 // --------------------------------------------------------------------------
 //
@@ -60,5 +72,5 @@
 //! @return the size of the file, in bytes
 //
-long FilesStatisticsService::GetFileSizeOnDisk(const string& file)
+int64_t DimWriteStatistics::GetFileSizeOnDisk(const string& file)
 {
      errno = 0;
@@ -67,13 +79,15 @@
          return st.st_size;
 
-     if (errno != 0 && errno != 2)//ignoring error #2: no such file or directory is not an error for new files
-     {
-         ostringstream str;
-         str << "Unable to stat " << file << ". Reason: " << strerror(errno) << " [" << errno << "]";
-         fMess->Error(str);
-     }
+     //ignoring error #2: no such file or directory is not an error for new files
+     if (errno == 0 || errno == 2)
+         return -1;
+
+     ostringstream str;
+     str << "stat() failed for '" << file << "': " << strerror(errno) << " [errno=" << errno << "]";
+     fLog.Error(str);
 
      return -1;
 }
+
 // --------------------------------------------------------------------------
 //
@@ -81,63 +95,63 @@
 //! @param folder the path to the folder
 //
-bool FilesStatisticsService::SetCurrentFolder(const string& folder)
-{
-    fMutex.lock();
+bool DimWriteStatistics::SetCurrentFolder(const string& folder)
+{
+    if (GetFreeSpace() == -1)
+    {
+        fLog.Error("statvfs() failed for '"+folder+"'... ignoring it.");
+        return false;
+    }
+
     fCurrentFolder = folder;
-
-    fStats.freeSpace = GetFreeSpace();
-    if (fStats.freeSpace == -1)
-    {
-        fMess->Error("Could not stat the given folder. Ignoring it");
-        fMutex.unlock();
-        return false;
-    }
-    fMutex.unlock();
     return true;
 }
+
 // --------------------------------------------------------------------------
 //
 //! Updates the service. This is the function executed by the thread
 //
-void FilesStatisticsService::UpdateService()
-{
-    Time cTime = Time();
+void DimWriteStatistics::UpdateService()
+{
     Time previousTime;
-    fStats.freeSpace = GetFreeSpace();
-    fService->updateService();
-    sleep(1);
-    while (fContinueStats)
-    {
-        if (fPeriodDuration == 0.0f)
+    uint64_t previousSize = 0;
+
+    while (1)
+    {
+        if (fUpdateInterval==0)
         {
-            sleep(0.1f);
+            boost::this_thread::interruption_point();
+            boost::this_thread::yield();
             continue;
         }
-        sleep(fPeriodDuration);
-        fMutex.lock();
+
+        Stats data;
+
+        for (set<string>::const_iterator it = fOpenedFiles.begin(); it != fOpenedFiles.end(); it++)
+            data.sizeWritten += GetFileSizeOnDisk(*it);
+        data.sizeWritten -= fBaseSize;
+
+        const Time cTime = Time();
+
+        data.freeSpace   = GetFreeSpace();
+        data.rateWritten = data.sizeWritten-previousSize;
+        data.timeElapsed = (cTime - previousTime).total_milliseconds();
+
+        previousSize = data.sizeWritten;
         previousTime = cTime;
-        cTime = Time();
-        fStats.freeSpace = GetFreeSpace();
-        //gather the size of opened files.
-        long previousSize = fStats.sizeWritten;
-        fStats.sizeWritten = 0;
-        for (set<string>::const_iterator it = fOpenedFiles.begin(); it != fOpenedFiles.end(); it++)
-            fStats.sizeWritten += GetFileSizeOnDisk(*it);
-        fStats.sizeWritten -= fBaseSize;
-        long timeElapsed = (cTime - previousTime).total_seconds();
-        if (timeElapsed != 0)
-            fStats.writingRate = (fStats.sizeWritten - previousSize)/timeElapsed;
-        else
-            fStats.writingRate = 0;
-        fService->updateService();
-        fMutex.unlock();
+
+        fDimService.Update(data);
+
+        fStats = data;
+
         if (fDebug)
         {
             ostringstream str;
-            str << "Size written: " << fStats.sizeWritten/1024 << " kB; writing rate: ";
-            str << fStats.writingRate/1024 << " kB/s; free space: ";
-            str << fStats.freeSpace/(1024*1024) << " MB";
-            fMess->Debug(str);
+            str << "Written: " << fStats.sizeWritten/1000 << " kB; writing rate: ";
+            str << fStats.rateWritten/fStats.timeElapsed << " kB/s; free space: ";
+            str << fStats.freeSpace/1000000 << " MB";
+            fLog.Debug(str);
         }
+
+        boost::this_thread::sleep(milliseconds(fUpdateInterval));
     }
 }
@@ -148,23 +162,20 @@
 //! @return whether this file could be stated or not
 //
-bool FilesStatisticsService::FileOpened(const string& fileName)
+bool DimWriteStatistics::FileOpened(const string& fileName)
 {
     if (fOpenedFiles.find(fileName) != fOpenedFiles.end())
         return false;
-    fMutex.lock();
+
     //Add a newly opened file, and remember its original size
-    long newSize = GetFileSizeOnDisk(fileName);
-    if (newSize != -1)
-    {
-        fBaseSize += newSize;
-        fOpenedFiles.insert(fileName);
-    }
-    else
-    {
-        fMess->Error("Could not stat file name: " + fileName);
-        fMutex.unlock();
+    const int64_t newSize = GetFileSizeOnDisk(fileName);
+    if (newSize == -1)
+    {
+        fLog.Error("Could not stat file name: " + fileName);
         return false;
     }
-    fMutex.unlock();
+
+    fBaseSize += newSize;
+    fOpenedFiles.insert(fileName);
+
     return true;
 }
@@ -174,16 +185,16 @@
 //! @param debug the new mode (true or false)
 //
-void FilesStatisticsService::SetDebugMode(bool debug)
+void DimWriteStatistics::SetDebugMode(bool debug)
 {
     if (fDebug == debug)
     {
-        fMess->Error("Debug mode already in the asked state");
+        fLog.Info("Debug mode already in the asked state.");
         return;
     }
+
     fDebug = debug;
+
     if (fDebug)
-    {
-        fMess->Debug("Debug mode is now on");
-    }
+        fLog.Debug("Debug mode is now on.");
 }
 // --------------------------------------------------------------------------
@@ -192,48 +203,26 @@
 //! @param duration the duration between two services update, in second
 //
-void FilesStatisticsService::SetStatPeriod(const float duration)
-{
-    if (duration < 0)
-    {
-        fMess->Error("Statistics period duration should be greater than zero. Discarding");
+void DimWriteStatistics::SetUpdateInterval(const int16_t duration)
+{
+    if (!finite(duration))
+    {
+        fLog.Error("Provided update interval is not a valid float... discarding.");
         return;
     }
-    if (!finite(duration))
-    {
-        fMess->Error("Provided duration does not appear to be a valid float. Discarding");
+    if (uint16_t(duration) == fUpdateInterval)
+    {
+        fLog.Warn("Statistics update interval not modified. Supplied value already in use.");
         return;
     }
-    if (duration == fPeriodDuration)
-        fMess->Warn("Statistics period not modified. Supplied value already in use");
-    if (duration == 0)
-        fMess->Message("Statistics are now OFF");
+
+    if (duration <= 0)
+        fLog.Message("Statistics are now OFF.");
     else
     {
         ostringstream str;
-        str << "Statistics period is now " << duration << " seconds";
-        fMess->Message(str);
-    }
-    fPeriodDuration = duration;
-}
-// --------------------------------------------------------------------------
-//
-//! Retrieves the latest calculated size written and free disk space
-//! @param the FileStatisticsData data structure to be filled in
-//
-void FilesStatisticsService::GetTotalSizeWritten(FileStatisticsData& data)
-{
-    data.sizeWritten = fStats.sizeWritten;
-    data.writingRate = fStats.writingRate;
-    data.freeSpace = fStats.freeSpace;
-}
-// --------------------------------------------------------------------------
-//
-//! Resets the files statistics object. Basically sets all counters to zero
-//
-void FilesStatisticsService::Reset()
-{
-    fStats.sizeWritten = 0;
-    fStats.writingRate = 0;
-    fBaseSize = 0;
-    fOpenedFiles.clear();
-}
+        str << "Statistics update interval is now " << duration << " seconds";
+        fLog.Message(str);
+    }
+
+    fUpdateInterval = duration<0 ? 0 : duration;
+}
