Changeset 11304
- Timestamp:
- 07/10/11 13:42:16 (13 years ago)
- Location:
- trunk/FACT++/src
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/FACT++/src/FilesStatisticsService.cc
r11292 r11304 1 //************************************************************************************* 2 /** @class DimWriteStatistics 3 4 @brief provides a statistics service telling the free space on disk and the total size written so far 5 6 */ 7 //************************************************************************************* 1 8 #include "FilesStatisticsService.h" 9 2 10 #include <sys/statvfs.h> //for getting disk free space 3 11 #include <sys/stat.h> //for getting files sizes 12 4 13 #include "Time.h" 5 // -------------------------------------------------------------------------- 6 // 7 //! Default constructor. Should NOT be used otherwise the service name will be wrong 8 // 9 //FilesStatisticsService::FilesStatisticsService() 10 //{ 11 // FilesStatisticsService("YouDidntCallTheProperConstructor"); 12 //} 14 15 using namespace std; 16 using namespace boost::posix_time; 17 13 18 // -------------------------------------------------------------------------- 14 19 // … … 17 22 //! @param serverName the name of the server which created this object 18 23 // 19 FilesStatisticsService::FilesStatisticsService(const string& serverName, MessageImp* mess) : fServerName(serverName), 20 fCurrentFolder("."), 21 fContinueStats(true), 22 fDebug(false), 23 fBaseSize(0), 24 fPeriodDuration(1), 25 fMess(mess) 26 { 27 fStats.sizeWritten = 0; 28 fStats.freeSpace = 0; 29 fStats.writingRate = 0; 30 fService = new DimDescribedService(serverName + "/STATS", "X:3", fStats, "Statistics about size written"); 31 fThread = boost::thread(boost::bind(&FilesStatisticsService::UpdateService, this)); 32 } 33 // -------------------------------------------------------------------------- 34 // 35 //! Default destructor. 36 // 37 FilesStatisticsService::~FilesStatisticsService() 38 { 39 fContinueStats = false; 40 //WARNING: DO NOT DO JOIN OTHERWISE THE DESTRUCTOR BLOCKS 41 // fThread.join(); 42 delete fService; 43 } 24 DimWriteStatistics::DimWriteStatistics(const string& server, MessageImp &log) : 25 fLog(log), 26 fDimService(server + "/STATS", "X:4", "Statistics about size written"), 27 fCurrentFolder("."), 28 fUpdateInterval(1000), 29 fBaseSize(0), 30 fDebug(false) 31 { 32 fThread = boost::thread(boost::bind(&DimWriteStatistics::UpdateService, this)); 33 } 34 35 // -------------------------------------------------------------------------- 36 // 37 //! Destructor. Stop thread by setting fUpdateInterval to 0 and join the 38 //! thread. 39 // 40 DimWriteStatistics::~DimWriteStatistics() 41 { 42 fUpdateInterval = 0; 43 44 // This blocks for fPeriod duration, but maybe canceling the thread 45 // could be more dangerous leaving Dim in an undefined state. 46 fThread.interrupt(); 47 } 48 49 int DimWriteStatistics::Write(const Time &t, const string &txt, int qos) 50 { 51 return fLog.Write(t, txt, qos); 52 } 53 44 54 // -------------------------------------------------------------------------- 45 55 // … … 47 57 //! @return the available free space on disk, in bytes 48 58 // 49 long FilesStatisticsService::GetFreeSpace()59 int64_t DimWriteStatistics::GetFreeSpace() 50 60 { 51 61 struct statvfs vfs; 52 62 if (statvfs(fCurrentFolder.c_str(), &vfs)) 53 63 return -1; 64 54 65 return vfs.f_bsize*vfs.f_bavail; 55 66 } 67 56 68 // -------------------------------------------------------------------------- 57 69 // … … 60 72 //! @return the size of the file, in bytes 61 73 // 62 long FilesStatisticsService::GetFileSizeOnDisk(const string& file)74 int64_t DimWriteStatistics::GetFileSizeOnDisk(const string& file) 63 75 { 64 76 errno = 0; … … 67 79 return st.st_size; 68 80 69 if (errno != 0 && errno != 2)//ignoring error #2: no such file or directory is not an error for new files 70 { 71 ostringstream str; 72 str << "Unable to stat " << file << ". Reason: " << strerror(errno) << " [" << errno << "]"; 73 fMess->Error(str); 74 } 81 //ignoring error #2: no such file or directory is not an error for new files 82 if (errno == 0 || errno == 2) 83 return -1; 84 85 ostringstream str; 86 str << "stat() failed for '" << file << "': " << strerror(errno) << " [errno=" << errno << "]"; 87 fLog.Error(str); 75 88 76 89 return -1; 77 90 } 91 78 92 // -------------------------------------------------------------------------- 79 93 // … … 81 95 //! @param folder the path to the folder 82 96 // 83 bool FilesStatisticsService::SetCurrentFolder(const string& folder) 84 { 85 fMutex.lock(); 97 bool DimWriteStatistics::SetCurrentFolder(const string& folder) 98 { 99 if (GetFreeSpace() == -1) 100 { 101 fLog.Error("statvfs() failed for '"+folder+"'... ignoring it."); 102 return false; 103 } 104 86 105 fCurrentFolder = folder; 87 88 fStats.freeSpace = GetFreeSpace();89 if (fStats.freeSpace == -1)90 {91 fMess->Error("Could not stat the given folder. Ignoring it");92 fMutex.unlock();93 return false;94 }95 fMutex.unlock();96 106 return true; 97 107 } 108 98 109 // -------------------------------------------------------------------------- 99 110 // 100 111 //! Updates the service. This is the function executed by the thread 101 112 // 102 void FilesStatisticsService::UpdateService() 103 { 104 Time cTime = Time(); 113 void DimWriteStatistics::UpdateService() 114 { 105 115 Time previousTime; 106 fStats.freeSpace = GetFreeSpace(); 107 fService->updateService(); 108 sleep(1); 109 while (fContinueStats) 110 { 111 if (fPeriodDuration == 0.0f) 116 uint64_t previousSize = 0; 117 118 while (1) 119 { 120 if (fUpdateInterval==0) 112 121 { 113 sleep(0.1f); 122 boost::this_thread::interruption_point(); 123 boost::this_thread::yield(); 114 124 continue; 115 125 } 116 sleep(fPeriodDuration); 117 fMutex.lock(); 126 127 Stats data; 128 129 for (set<string>::const_iterator it = fOpenedFiles.begin(); it != fOpenedFiles.end(); it++) 130 data.sizeWritten += GetFileSizeOnDisk(*it); 131 data.sizeWritten -= fBaseSize; 132 133 const Time cTime = Time(); 134 135 data.freeSpace = GetFreeSpace(); 136 data.rateWritten = data.sizeWritten-previousSize; 137 data.timeElapsed = (cTime - previousTime).total_milliseconds(); 138 139 previousSize = data.sizeWritten; 118 140 previousTime = cTime; 119 cTime = Time(); 120 fStats.freeSpace = GetFreeSpace(); 121 //gather the size of opened files. 122 long previousSize = fStats.sizeWritten; 123 fStats.sizeWritten = 0; 124 for (set<string>::const_iterator it = fOpenedFiles.begin(); it != fOpenedFiles.end(); it++) 125 fStats.sizeWritten += GetFileSizeOnDisk(*it); 126 fStats.sizeWritten -= fBaseSize; 127 long timeElapsed = (cTime - previousTime).total_seconds(); 128 if (timeElapsed != 0) 129 fStats.writingRate = (fStats.sizeWritten - previousSize)/timeElapsed; 130 else 131 fStats.writingRate = 0; 132 fService->updateService(); 133 fMutex.unlock(); 141 142 fDimService.Update(data); 143 144 fStats = data; 145 134 146 if (fDebug) 135 147 { 136 148 ostringstream str; 137 str << " Size written: " << fStats.sizeWritten/1024<< " kB; writing rate: ";138 str << fStats. writingRate/1024<< " kB/s; free space: ";139 str << fStats.freeSpace/ (1024*1024)<< " MB";140 f Mess->Debug(str);149 str << "Written: " << fStats.sizeWritten/1000 << " kB; writing rate: "; 150 str << fStats.rateWritten/fStats.timeElapsed << " kB/s; free space: "; 151 str << fStats.freeSpace/1000000 << " MB"; 152 fLog.Debug(str); 141 153 } 154 155 boost::this_thread::sleep(milliseconds(fUpdateInterval)); 142 156 } 143 157 } … … 148 162 //! @return whether this file could be stated or not 149 163 // 150 bool FilesStatisticsService::FileOpened(const string& fileName)164 bool DimWriteStatistics::FileOpened(const string& fileName) 151 165 { 152 166 if (fOpenedFiles.find(fileName) != fOpenedFiles.end()) 153 167 return false; 154 fMutex.lock(); 168 155 169 //Add a newly opened file, and remember its original size 156 long newSize = GetFileSizeOnDisk(fileName); 157 if (newSize != -1) 158 { 159 fBaseSize += newSize; 160 fOpenedFiles.insert(fileName); 161 } 162 else 163 { 164 fMess->Error("Could not stat file name: " + fileName); 165 fMutex.unlock(); 170 const int64_t newSize = GetFileSizeOnDisk(fileName); 171 if (newSize == -1) 172 { 173 fLog.Error("Could not stat file name: " + fileName); 166 174 return false; 167 175 } 168 fMutex.unlock(); 176 177 fBaseSize += newSize; 178 fOpenedFiles.insert(fileName); 179 169 180 return true; 170 181 } … … 174 185 //! @param debug the new mode (true or false) 175 186 // 176 void FilesStatisticsService::SetDebugMode(bool debug)187 void DimWriteStatistics::SetDebugMode(bool debug) 177 188 { 178 189 if (fDebug == debug) 179 190 { 180 f Mess->Error("Debug mode already in the asked state");191 fLog.Info("Debug mode already in the asked state."); 181 192 return; 182 193 } 194 183 195 fDebug = debug; 196 184 197 if (fDebug) 185 { 186 fMess->Debug("Debug mode is now on"); 187 } 198 fLog.Debug("Debug mode is now on."); 188 199 } 189 200 // -------------------------------------------------------------------------- … … 192 203 //! @param duration the duration between two services update, in second 193 204 // 194 void FilesStatisticsService::SetStatPeriod(const float duration)195 { 196 if ( duration < 0)197 { 198 f Mess->Error("Statistics period duration should be greater than zero. Discarding");205 void DimWriteStatistics::SetUpdateInterval(const int16_t duration) 206 { 207 if (!finite(duration)) 208 { 209 fLog.Error("Provided update interval is not a valid float... discarding."); 199 210 return; 200 211 } 201 if ( !finite(duration))202 { 203 f Mess->Error("Provided duration does not appear to be a valid float. Discarding");212 if (uint16_t(duration) == fUpdateInterval) 213 { 214 fLog.Warn("Statistics update interval not modified. Supplied value already in use."); 204 215 return; 205 216 } 206 if (duration == fPeriodDuration) 207 fMess->Warn("Statistics period not modified. Supplied value already in use"); 208 if (duration == 0) 209 fMess->Message("Statistics are now OFF"); 217 218 if (duration <= 0) 219 fLog.Message("Statistics are now OFF."); 210 220 else 211 221 { 212 222 ostringstream str; 213 str << "Statistics period is now " << duration << " seconds"; 214 fMess->Message(str); 215 } 216 fPeriodDuration = duration; 217 } 218 // -------------------------------------------------------------------------- 219 // 220 //! Retrieves the latest calculated size written and free disk space 221 //! @param the FileStatisticsData data structure to be filled in 222 // 223 void FilesStatisticsService::GetTotalSizeWritten(FileStatisticsData& data) 224 { 225 data.sizeWritten = fStats.sizeWritten; 226 data.writingRate = fStats.writingRate; 227 data.freeSpace = fStats.freeSpace; 228 } 229 // -------------------------------------------------------------------------- 230 // 231 //! Resets the files statistics object. Basically sets all counters to zero 232 // 233 void FilesStatisticsService::Reset() 234 { 235 fStats.sizeWritten = 0; 236 fStats.writingRate = 0; 237 fBaseSize = 0; 238 fOpenedFiles.clear(); 239 } 223 str << "Statistics update interval is now " << duration << " seconds"; 224 fLog.Message(str); 225 } 226 227 fUpdateInterval = duration<0 ? 0 : duration; 228 } -
trunk/FACT++/src/FilesStatisticsService.h
r11292 r11304 1 //************************************************************************************* 2 /** @class FilesStatisticsService 3 * 4 * @brief provides a statistics service telling the free space on disk and the total size written so far 5 * 6 */ 7 //************************************************************************************* 8 #ifndef FILESSTATISTICSSERVICE_H_ 9 #define FILESSTATISTICSSERVICE_H_ 1 #ifndef FACT_DimWriteStatistics 2 #define FACT_DimWriteStatistics 10 3 11 4 #include "MessageDim.h" 5 12 6 #include <boost/thread.hpp> 13 #include <mutex> 7 14 8 #include <string> 15 9 #include <set> 16 10 17 using namespace std; 11 class DimWriteStatistics 12 { 13 public: 14 struct Stats 15 { 16 uint64_t freeSpace; 17 uint64_t sizeWritten; 18 uint64_t rateWritten; 19 uint64_t timeElapsed; 18 20 19 struct FileStatisticsData { 20 long sizeWritten; 21 long freeSpace; 22 long writingRate; 23 }; 24 class FilesStatisticsService 25 { 21 Stats() : freeSpace(0), sizeWritten(0), rateWritten(0), timeElapsed(0) { } 22 }; 23 26 24 private: 27 ///The name of the server which created the object 28 string fServerName; 29 ///The current folder being watched for free space 30 string fCurrentFolder; 31 ///The boost thread used to update the service 32 boost::thread fThread; 33 ///The data structure holding the stat data 34 FileStatisticsData fStats; 35 ///The mutex used to make sure that the service isn't updated while changing conf. 36 mutex fMutex; 37 ///the Dim service 38 DimDescribedService* fService; 39 ///Bool indicating if main loop should be exited 40 bool fContinueStats; 41 ///Bool indicating if debug information should be printed 25 MessageImp &fLog; 26 27 DimDescribedService fDimService; 28 29 std::string fCurrentFolder; /// Current folder being watched for free space 30 uint16_t fUpdateInterval; /// Duration, in millisecond between two service updates. 0 means no more updates 31 size_t fBaseSize; /// Total base size of all opened files 32 std::set<std::string> fOpenedFiles; /// List of all opened files. set is used to easily check for entries 33 34 /// Bool indicating if debug information should be printed 42 35 bool fDebug; 36 37 /// The data structure holding the stat data 38 Stats fStats; 39 40 /// The boost thread used to update the service 41 boost::thread fThread; 42 43 43 ///Main loop 44 44 void UpdateService(); 45 45 46 ///Returns the free space on the disk of the folder being watched (fCurrentFolder) 46 long GetFreeSpace(); 47 int64_t GetFreeSpace(); 48 47 49 ///Returns the size on disk of a given file 48 long GetFileSizeOnDisk(const string& file); 49 ///This is the total base size of all opened files 50 long fBaseSize; 51 ///This is the list of all opened files. set is used to easily check for entries 52 set<string> fOpenedFiles; 53 ///This is the duration, in second between two service updates. 0 means no more updates 54 float fPeriodDuration; 55 ///This is the MessageImp object used for messaging 56 MessageImp* fMess; 50 int64_t GetFileSizeOnDisk(const std::string& file); 51 52 int Write(const Time &t, const std::string &txt, int qos); 53 57 54 public: 58 55 ///Constructor 59 FilesStatisticsService(const string& serverName, MessageImp* mess);56 DimWriteStatistics(const std::string& serverName, MessageImp &log); 60 57 ///Default destructor 61 ~FilesStatisticsService(); 58 ~DimWriteStatistics(); 59 62 60 ///Configures that current folder where files are written to 63 bool SetCurrentFolder(const string& folder); 64 bool FileOpened(const string& fileName); 61 bool SetCurrentFolder(const std::string& folder); 62 63 bool FileOpened(const std::string& fileName); 64 65 65 void SetDebugMode(bool); 66 void Set StatPeriod(const float duration);67 void GetTotalSizeWritten(FileStatisticsData& data); 68 void Reset();66 void SetUpdateInterval(const int16_t millisec); 67 68 const Stats &GetTotalSizeWritten() const { return fStats; } 69 69 }; 70 70 71 #endif /* FILESSTATISTICSSERVICE_H_ */71 #endif
Note:
See TracChangeset
for help on using the changeset viewer.