XRootD
Loading...
Searching...
No Matches
XrdSysTimer.cc
Go to the documentation of this file.
1/******************************************************************************/
2/* */
3/* X r d S y s T i m e r . c c */
4/* */
5/* (c) 2004 by the Board of Trustees of the Leland Stanford, Jr., University */
6/* Produced by Andrew Hanushevsky for Stanford University under contract */
7/* DE-AC02-76-SFO0515 with the Department of Energy */
8/* */
9/* This file is part of the XRootD software suite. */
10/* */
11/* XRootD is free software: you can redistribute it and/or modify it under */
12/* the terms of the GNU Lesser General Public License as published by the */
13/* Free Software Foundation, either version 3 of the License, or (at your */
14/* option) any later version. */
15/* */
16/* XRootD is distributed in the hope that it will be useful, but WITHOUT */
17/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
18/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
19/* License for more details. */
20/* */
21/* You should have received a copy of the GNU Lesser General Public License */
22/* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
23/* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
24/* */
25/* The copyright holder's institutional names and contributor's names may not */
26/* be used to endorse or promote products derived from this software without */
27/* specific prior written permission of the institution or contributor. */
28/******************************************************************************/
29
30#ifndef WIN32
31#include <unistd.h>
32#else
33#include "XrdSys/XrdWin32.hh"
34#endif
35#include <cerrno>
36#include <ctime>
37#include <cstdio>
38#include "XrdSys/XrdSysTimer.hh"
39#include <iostream>
40
41/******************************************************************************/
42/* D e l t a _ T i m e */
43/******************************************************************************/
44
45struct timeval *XrdSysTimer::Delta_Time(struct timeval &tbeg)
46{
47 gettimeofday(&LastReport, 0);
48 LastReport.tv_sec = LastReport.tv_sec - tbeg.tv_sec;
49 LastReport.tv_usec = LastReport.tv_usec - tbeg.tv_usec;
50 if (LastReport.tv_usec < 0) {LastReport.tv_sec--; LastReport.tv_usec += 1000000;}
51 return &LastReport;
52}
53
54/******************************************************************************/
55/* M i d n i g h t */
56/******************************************************************************/
57
58// Midnight() uses localtime_r() and no mktime(). The latter calls tzset(),
59// which reads TZ with getenv() on each call, and the logger calls Midnight()
60// in a thread while the configuration adds variables to the environment. With
61// glibc before 2.40, that getenv() can read the environment array which a
62// concurrent putenv() has just freed. localtime_r() reads TZ only once, and
63// main() calls tzset() before it starts any thread.
64
65namespace
66{
67// The seconds since the local midnight of the day of t
68//
69long SecondsOfDay(time_t t)
70{
71 struct tm tmv;
72 localtime_r(&t, &tmv);
73 return tmv.tm_hour*3600L + tmv.tm_min*60L + tmv.tm_sec;
74}
75}
76
77time_t XrdSysTimer::Midnight(time_t tnow)
78{
79 time_t add_time;
80
81// Compute time at midnight, today (tnow 0) or at the end of today (tnow 1)
82//
83 if (tnow == 0 || tnow == 1) {add_time = tnow; tnow = time(0);}
84 else add_time = 0;
85
86 time_t midnight = tnow - SecondsOfDay(tnow);
87 if (add_time) midnight += 86400;
88
89// On the day of a daylight saving change, a day is not 86400 seconds long, and
90// the result can be an hour off. Correct it to the nearest local midnight. In
91// a zone where the clock jumps from 00:00 to 01:00, the day has no midnight
92// and starts at the change; a step back from it would give 23:00 of the day
93// before, thus keep the result when the step back does not end at midnight.
94//
95 long secs = SecondsOfDay(midnight);
96 if (secs >= 43200) midnight += 86400 - secs;
97 else if (secs && !SecondsOfDay(midnight - secs)) midnight -= secs;
98 return midnight;
99}
100
101/******************************************************************************/
102/* R e p o r t */
103/******************************************************************************/
104
105unsigned long XrdSysTimer::Report()
106{
107 unsigned long current_time;
108
109// Get current time of day
110//
111 gettimeofday(&LastReport, 0);
112 current_time = (unsigned long)LastReport.tv_sec;
113
114// Calculate the time interval thus far
115//
116 LastReport.tv_sec = LastReport.tv_sec - StopWatch.tv_sec;
117 LastReport.tv_usec = LastReport.tv_usec - StopWatch.tv_usec;
118 if (LastReport.tv_usec < 0)
119 {LastReport.tv_sec--; LastReport.tv_usec += 1000000;}
120
121// Return the current time
122//
123 return current_time;
124}
125
126/******************************************************************************/
127
128unsigned long XrdSysTimer::Report(double &Total_Time)
129{
130 unsigned long report_time = Report();
131
132// Add up the time as a double
133//
134 Total_Time += static_cast<double>(LastReport.tv_sec) +
135 static_cast<double>(LastReport.tv_usec/1000)/1000.0;
136
137// Return time
138//
139 return report_time;
140}
141
142/******************************************************************************/
143
144unsigned long XrdSysTimer::Report(unsigned long &Total_Time)
145{
146 unsigned long report_time = Report();
147
148// Add up the time as a 32-bit value to nearest milliseconds (max = 24 days)
149//
150 Total_Time += (unsigned long)LastReport.tv_sec*1000 +
151 (unsigned long)(LastReport.tv_usec/1000);
152
153// Return time
154//
155 return report_time;
156}
157
158/******************************************************************************/
159
160unsigned long XrdSysTimer::Report(unsigned long long &Total_Time)
161{
162 unsigned long report_time = Report();
163
164// Add up the time as a 64-bit value to nearest milliseconds
165//
166 Total_Time += (unsigned long long)LastReport.tv_sec*1000 +
167 (unsigned long long)(LastReport.tv_usec/1000);
168
169// Return time
170//
171 return report_time;
172}
173
174/******************************************************************************/
175
176unsigned long XrdSysTimer::Report(struct timeval &Total_Time)
177{
178 unsigned long report_time = Report();
179
180// Add the interval to the interval total time so far
181//
182 Total_Time.tv_sec += LastReport.tv_sec;
183 Total_Time.tv_usec += LastReport.tv_usec;
184 if (Total_Time.tv_usec > 1000000) {Total_Time.tv_sec++;
185 Total_Time.tv_usec -= 1000000;}
186
187// Return time
188//
189 return report_time;
190}
191
192/******************************************************************************/
193/* S n o o z e */
194/******************************************************************************/
195
197{
198#ifndef WIN32
199 struct timespec naptime, waketime;
200
201// Calculate nano sleep time
202//
203 naptime.tv_sec = sec;
204 naptime.tv_nsec = 0;
205
206// Wait for a lsoppy number of seconds
207//
208 while(nanosleep(&naptime, &waketime) && EINTR == errno)
209 {naptime.tv_sec = waketime.tv_sec;
210 naptime.tv_nsec = waketime.tv_nsec;
211 }
212#else
213 ::Sleep(sec*1000);
214#endif
215}
216/******************************************************************************/
217/* s 2 h m s */
218/******************************************************************************/
219
220char *XrdSysTimer::s2hms(int sec, char *buff, int blen)
221{
222 int hours, minutes;
223
224 minutes = sec/60;
225 sec = sec%60;
226 hours = minutes/60;
227 minutes = minutes%60;
228
229 snprintf(buff, blen-1, "%d:%02d:%02d", hours, minutes, sec);
230 buff[blen-1] = '\0';
231 return buff;
232}
233
234/******************************************************************************/
235/* T i m e Z o n e */
236/******************************************************************************/
237
239{
240 time_t currTime = time(0);
241 time_t currTimeGMT = 0;
242 tm ptm;
243
244 gmtime_r( &currTime, &ptm );
245 currTimeGMT = mktime( &ptm );
246 currTime /= 60*60;
247 currTimeGMT /= 60*60;
248 return currTime - currTimeGMT;
249}
250
251/******************************************************************************/
252/* W a i t */
253/******************************************************************************/
254
255void XrdSysTimer::Wait(int mills)
256{
257#ifndef WIN32
258 struct timespec naptime, waketime;
259
260// Calculate nano sleep time
261//
262 naptime.tv_sec = mills/1000;
263 naptime.tv_nsec = (mills%1000)*1000000;
264
265// Wait for exactly x milliseconds
266//
267 while(nanosleep(&naptime, &waketime) && EINTR == errno)
268 {naptime.tv_sec = waketime.tv_sec;
269 naptime.tv_nsec = waketime.tv_nsec;
270 }
271#else
272 ::Sleep(mills);
273#endif
274}
275
276/******************************************************************************/
277/* W a i t 4 M i d n i g h t */
278/******************************************************************************/
279
281{
282
283// Wait until midnight arrives
284//
285#ifndef __APPLE__
286 timespec Midnite = {Midnight(1), 0};
287 while(clock_nanosleep(CLOCK_REALTIME,TIMER_ABSTIME,&Midnite,0) == EINTR) {}
288#else
289 timespec tleft, Midnite = {Midnight(1) - time(0), 0};
290 int ntpWait = 60;
291do{while(nanosleep(&Midnite, &tleft) && EINTR == errno)
292 {Midnite.tv_sec = tleft.tv_sec;
293 Midnite.tv_nsec = tleft.tv_nsec;
294 }
295 if (Midnight(1) - time(0) >= 60) break;
296 Midnite.tv_sec = 1;
297 Midnite.tv_nsec = 0;
298 } while(ntpWait--); // This avoids multiple wakeups when NTP adjusts clock
299#endif
300}
static void Wait4Midnight()
static char * s2hms(int sec, char *buff, int blen)
static time_t Midnight(time_t tnow=0)
struct timeval * Delta_Time(struct timeval &tbeg)
static void Snooze(int seconds)
static int TimeZone()
unsigned long Report(double &)
static void Wait(int milliseconds)