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

Last change on this file since 11495 was 11318, checked in by tbretz, 13 years ago
Removed souble error message.
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)
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 fLog.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.