source: trunk/FACT++/src/DimWriteStatistics.cc@ 11575

Last change on this file since 11575 was 11534, checked in by tbretz, 13 years ago
Changed GetFileSizeOnDisk to be static so it can be accessed from the outside.
File size: 6.2 KB
Line 
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//*************************************************************************************
8#include "DimWriteStatistics.h"
9
10#include <sys/statvfs.h> //for getting disk free space
11#include <sys/stat.h> //for getting files sizes
12
13#include "Time.h"
14
15using namespace std;
16using namespace boost::posix_time;
17
18// --------------------------------------------------------------------------
19//
20//! Constructor with correct service name. The state machine using this object should give it
21//! its own name as a parameter
22//! @param serverName the name of the server which created this object
23//
24DimWriteStatistics::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//
40DimWriteStatistics::~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
49int DimWriteStatistics::Write(const Time &t, const string &txt, int qos)
50{
51 return fLog.Write(t, txt, qos);
52}
53
54// --------------------------------------------------------------------------
55//
56//! Retrieves the free space of the current base path
57//! @return the available free space on disk, in bytes
58//
59int64_t DimWriteStatistics::GetFreeSpace()
60{
61 struct statvfs vfs;
62 if (statvfs(fCurrentFolder.c_str(), &vfs))
63 return -1;
64
65 return vfs.f_bsize*vfs.f_bavail;
66}
67
68// --------------------------------------------------------------------------
69//
70//! Retrieves the size on disk of a given file, in bytes
71//! @param file the filename for which the size should be retrieved
72//! @return the size of the file, in bytes
73//
74int64_t DimWriteStatistics::GetFileSizeOnDisk(const string& file, MessageImp &log)
75{
76 errno = 0;
77 struct stat st;
78 if (!stat(file.c_str(), &st))
79 return st.st_size;
80
81 //ignoring error #2: no such file or directory is not an error for new files
82 if (errno == 0 || errno == 2)
83 return 0;
84
85 ostringstream str;
86 str << "stat() failed for '" << file << "': " << strerror(errno) << " [errno=" << errno << "]";
87 log.Error(str);
88
89 return -1;
90}
91
92// --------------------------------------------------------------------------
93//
94//! Sets the current folder
95//! @param folder the path to the folder
96//
97bool 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
105 fCurrentFolder = folder;
106 return true;
107}
108
109// --------------------------------------------------------------------------
110//
111//! Updates the service. This is the function executed by the thread
112//
113void DimWriteStatistics::UpdateService()
114{
115 Time previousTime;
116 uint64_t previousSize = 0;
117
118 while (1)
119 {
120 if (fUpdateInterval==0)
121 {
122 boost::this_thread::interruption_point();
123 boost::this_thread::yield();
124 continue;
125 }
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;
140 previousTime = cTime;
141
142 fDimService.Update(data);
143
144 fStats = data;
145
146 if (fDebug)
147 {
148 ostringstream 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);
153 }
154
155 boost::this_thread::sleep(milliseconds(fUpdateInterval));
156 }
157}
158// --------------------------------------------------------------------------
159//
160//! Let the object know that a new file has been opened
161//! @param fileName the full name of the file newly opened
162//! @return whether this file could be stated or not
163//
164bool DimWriteStatistics::FileOpened(const string& fileName)
165{
166 if (fOpenedFiles.find(fileName) != fOpenedFiles.end())
167 return false;
168
169 //Add a newly opened file, and remember its original size
170 const int64_t newSize = GetFileSizeOnDisk(fileName);
171 if (newSize == -1)
172 return false;
173
174 fBaseSize += newSize;
175 fOpenedFiles.insert(fileName);
176
177 return true;
178}
179// --------------------------------------------------------------------------
180//
181//! Set the debug mode on and off
182//! @param debug the new mode (true or false)
183//
184void DimWriteStatistics::SetDebugMode(bool debug)
185{
186 fDebug = debug;
187
188 if (fDebug)
189 fLog.Debug("Debug mode is now on.");
190}
191// --------------------------------------------------------------------------
192//
193//! Set the update of the service interval
194//! @param duration the duration between two services update, in second
195//
196void DimWriteStatistics::SetUpdateInterval(const int16_t duration)
197{
198 if (!finite(duration))
199 {
200 fLog.Error("Provided update interval is not a valid float... discarding.");
201 return;
202 }
203 if (uint16_t(duration) == fUpdateInterval)
204 {
205 fLog.Warn("Statistics update interval not modified. Supplied value already in use.");
206 return;
207 }
208
209 if (duration <= 0)
210 fLog.Message("Statistics are now OFF.");
211 else
212 {
213 ostringstream str;
214 str << "Statistics update interval is now " << duration << " seconds";
215 fLog.Message(str);
216 }
217
218 fUpdateInterval = duration<0 ? 0 : duration;
219}
Note: See TracBrowser for help on using the repository browser.