source: trunk/FACT++/src/FilesStatisticsService.cc@ 11291

Last change on this file since 11291 was 11291, checked in by lyard, 13 years ago
Little changes and cosmetics with statistics service
File size: 7.9 KB
Line 
1#include "FilesStatisticsService.h"
2#include <sys/statvfs.h> //for getting disk free space
3#include <sys/stat.h> //for getting files sizes
4#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//}
13// --------------------------------------------------------------------------
14//
15//! Constructor with correct service name. The state machine using this object should give it
16//! its own name as a parameter
17//! @param serverName the name of the server which created this object
18//
19FilesStatisticsService::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//
37FilesStatisticsService::~FilesStatisticsService()
38{
39 fContinueStats = false;
40//WARNING: DO NOT DO JOIN OTHERWISE THE DESTRUCTOR BLOCKS
41// fThread.join();
42 delete fService;
43}
44// --------------------------------------------------------------------------
45//
46//! Retrieves the free space of the current base path
47//! @return the available free space on disk, in bytes
48//
49long FilesStatisticsService::GetFreeSpace()
50{
51 struct statvfs vfs;
52 if (statvfs(fCurrentFolder.c_str(), &vfs))
53 return -1;
54 return vfs.f_bsize*vfs.f_bavail;
55}
56// --------------------------------------------------------------------------
57//
58//! Retrieves the size on disk of a given file, in bytes
59//! @param file the filename for which the size should be retrieved
60//! @return the size of the file, in bytes
61//
62long FilesStatisticsService::GetFileSizeOnDisk(const string& file)
63{
64 errno = 0;
65 struct stat st;
66 if (!stat(file.c_str(), &st))
67 return st.st_size;
68
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 }
75
76 return -1;
77}
78// --------------------------------------------------------------------------
79//
80//! Sets the current folder
81//! @param folder the path to the folder
82//
83bool FilesStatisticsService::SetCurrentFolder(const string& folder)
84{
85 fMutex.lock();
86 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 return true;
97}
98// --------------------------------------------------------------------------
99//
100//! Updates the service. This is the function executed by the thread
101//
102void FilesStatisticsService::UpdateService()
103{
104 Time cTime = Time();
105 Time previousTime;
106 fStats.freeSpace = GetFreeSpace();
107 fService->updateService();
108 sleep(1);
109 while (fContinueStats)
110 {
111 if (fPeriodDuration == 0.0f)
112 {
113 sleep(0.1f);
114 continue;
115 }
116 sleep(fPeriodDuration);
117 fMutex.lock();
118 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();
134 if (fDebug)
135 {
136 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 fMess->Debug(str);
141 }
142 }
143}
144// --------------------------------------------------------------------------
145//
146//! Let the object know that a new file has been opened
147//! @param fileName the full name of the file newly opened
148//! @return whether this file could be stated or not
149//
150bool FilesStatisticsService::FileOpened(const string& fileName)
151{
152 if (fOpenedFiles.find(fileName) != fOpenedFiles.end())
153 return false;
154 fMutex.lock();
155 //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();
166 return false;
167 }
168 fMutex.unlock();
169 return true;
170}
171// --------------------------------------------------------------------------
172//
173//! Set the debug mode on and off
174//! @param debug the new mode (true or false)
175//
176void FilesStatisticsService::SetDebugMode(bool debug)
177{
178 if (fDebug == debug)
179 {
180 fMess->Error("Debug mode already in the asked state");
181 return;
182 }
183 fDebug = debug;
184 if (fDebug)
185 {
186 fMess->Debug("Debug mode is now on");
187 }
188}
189// --------------------------------------------------------------------------
190//
191//! Set the update of the service interval
192//! @param duration the duration between two services update, in second
193//
194void FilesStatisticsService::SetStatPeriod(float duration)
195{
196 if (duration < 0)
197 {
198 fMess->Error("Statistics period duration should be greater than zero. Discarding");
199 return;
200 }
201 if (!finite(duration))
202 {
203 fMess->Error("Provided duration does not appear to be a valid float. Discarding");
204 return;
205 }
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");
210 else
211 {
212 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//
223void 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//
233void FilesStatisticsService::Reset()
234{
235 fStats.sizeWritten = 0;
236 fStats.writingRate = 0;
237 fBaseSize = 0;
238 fOpenedFiles.clear();
239}
Note: See TracBrowser for help on using the repository browser.