OR
[oweals/gnunet.git] / src / util / time.c
1 /*
2      This file is part of GNUnet.
3      (C) 2001, 2002, 2006, 2009 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 2, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file util/time.c
23  * @author Christian Grothoff
24  * @brief functions for handling time and time arithmetic
25  */
26 #include "platform.h"
27 #include "gnunet_time_lib.h"
28
29
30 /**
31  * Get the current time (works just as "time", just that we use the
32  * unit of time that the cron-jobs use (and is 64 bit)).
33  *
34  * @return the current time
35  */
36 struct GNUNET_TIME_Absolute
37 GNUNET_TIME_absolute_get ()
38 {
39   struct GNUNET_TIME_Absolute ret;
40   struct timeval tv;
41
42   GETTIMEOFDAY (&tv, NULL);
43   ret.value =
44     (uint64_t) (((uint64_t) tv.tv_sec * 1000LL) +
45                 ((uint64_t) tv.tv_usec / 1000LL));
46   return ret;
47 }
48
49
50 /**
51  * Return relative time of 0ms.
52  */
53 struct GNUNET_TIME_Relative
54 GNUNET_TIME_relative_get_zero ()
55 {
56   static struct GNUNET_TIME_Relative zero;
57   return zero;
58 }
59
60
61 /**
62  * Return absolute time of 0ms.
63  */
64 struct GNUNET_TIME_Absolute
65 GNUNET_TIME_absolute_get_zero ()
66 {
67   static struct GNUNET_TIME_Absolute zero;
68   return zero;
69 }
70
71 /**
72  * Return relative time of 1ms.
73  */
74 struct GNUNET_TIME_Relative
75 GNUNET_TIME_relative_get_unit ()
76 {
77   static struct GNUNET_TIME_Relative one = { 1 };
78   return one;
79 }
80
81 /**
82  * Return "forever".
83  */
84 struct GNUNET_TIME_Relative
85 GNUNET_TIME_relative_get_forever ()
86 {
87   static struct GNUNET_TIME_Relative forever = { (uint64_t) - 1LL };
88   return forever;
89 }
90
91 /**
92  * Return "forever".
93  */
94 struct GNUNET_TIME_Absolute
95 GNUNET_TIME_absolute_get_forever ()
96 {
97   static struct GNUNET_TIME_Absolute forever = { (uint64_t) - 1LL };
98   return forever;
99 }
100
101 /**
102  * Convert relative time to an absolute time in the
103  * future.
104  *
105  * @return timestamp that is "rel" in the future, or FOREVER if rel==FOREVER (or if we would overflow)
106  */
107 struct GNUNET_TIME_Absolute
108 GNUNET_TIME_relative_to_absolute (struct GNUNET_TIME_Relative rel)
109 {
110   struct GNUNET_TIME_Absolute ret;
111   if (rel.value == (uint64_t) - 1LL)
112     return GNUNET_TIME_absolute_get_forever ();
113   struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
114   if (rel.value + now.value < rel.value)
115     {
116       GNUNET_break (0);         /* overflow... */
117       return GNUNET_TIME_absolute_get_forever ();
118     }
119   ret.value = rel.value + now.value;
120   return ret;
121 }
122
123
124 /**
125  * Return the minimum of two relative time values.
126  *
127  * @param t1 first timestamp
128  * @param t2 other timestamp
129  * @return timestamp that is smaller
130  */
131 struct GNUNET_TIME_Relative
132 GNUNET_TIME_relative_min (struct
133                           GNUNET_TIME_Relative
134                           t1, struct GNUNET_TIME_Relative t2)
135 {
136   return (t1.value < t2.value) ? t1 : t2;
137 }
138
139
140
141 /**
142  * Return the minimum of two relative time values.
143  *
144  * @param t1 first timestamp
145  * @param t2 other timestamp
146  * @return timestamp that is smaller
147  */
148 struct GNUNET_TIME_Absolute
149 GNUNET_TIME_absolute_min (struct
150                           GNUNET_TIME_Absolute
151                           t1, struct GNUNET_TIME_Absolute t2)
152 {
153   return (t1.value < t2.value) ? t1 : t2;
154 }
155
156
157 /**
158  * Return the maximum of two relative time values.
159  *
160  * @param t1 first timestamp
161  * @param t2 other timestamp
162  * @return timestamp that is smaller
163  */
164 struct GNUNET_TIME_Absolute
165 GNUNET_TIME_absolute_max (struct
166                           GNUNET_TIME_Absolute
167                           t1, struct GNUNET_TIME_Absolute t2)
168 {
169   return (t1.value > t2.value) ? t1 : t2;
170 }
171
172
173 /**
174  * Given a timestamp in the future, how much time
175  * remains until then?
176  *
177  * @return future - now, or 0 if now >= future, or FOREVER if future==FOREVER.
178  */
179 struct GNUNET_TIME_Relative
180 GNUNET_TIME_absolute_get_remaining (struct GNUNET_TIME_Absolute future)
181 {
182   struct GNUNET_TIME_Relative ret;
183   if (future.value == (uint64_t) - 1LL)
184     return GNUNET_TIME_relative_get_forever ();
185   struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
186   if (now.value > future.value)
187     return GNUNET_TIME_relative_get_zero ();
188   ret.value = future.value - now.value;
189   return ret;
190 }
191
192 /**
193  * Compute the time difference between the given start and end times.
194  * Use this function instead of actual subtraction to ensure that
195  * "FOREVER" and overflows are handeled correctly.
196  *
197  * @return 0 if start >= end; FOREVER if end==FOREVER; otherwise end - start
198  */
199 struct GNUNET_TIME_Relative
200 GNUNET_TIME_absolute_get_difference (struct GNUNET_TIME_Absolute start,
201                                      struct GNUNET_TIME_Absolute end)
202 {
203   struct GNUNET_TIME_Relative ret;
204   if (end.value == (uint64_t) - 1LL)
205     return GNUNET_TIME_relative_get_forever ();
206   if (end.value < start.value)
207     return GNUNET_TIME_relative_get_zero ();
208   ret.value = end.value - start.value;
209   return ret;
210 }
211
212 /**
213  * Get the duration of an operation as the
214  * difference of the current time and the given start time "hence".
215  *
216  * @return aborts if hence==FOREVER, 0 if hence > now, otherwise now-hence.
217  */
218 struct GNUNET_TIME_Relative
219 GNUNET_TIME_absolute_get_duration (struct GNUNET_TIME_Absolute hence)
220 {
221   struct GNUNET_TIME_Absolute now;
222   struct GNUNET_TIME_Relative ret;
223
224   now = GNUNET_TIME_absolute_get ();
225   GNUNET_assert (hence.value != (uint64_t) - 1LL);
226   if (hence.value > now.value)
227     return GNUNET_TIME_relative_get_zero ();
228   ret.value = now.value - hence.value;
229   return ret;
230 }
231
232
233 /**
234  * Add a given relative duration to the
235  * given start time.
236  *
237  * @return FOREVER if either argument is FOREVER or on overflow; start+duration otherwise
238  */
239 struct GNUNET_TIME_Absolute
240 GNUNET_TIME_absolute_add (struct GNUNET_TIME_Absolute start,
241                           struct GNUNET_TIME_Relative duration)
242 {
243   struct GNUNET_TIME_Absolute ret;
244
245   if ((start.value == (uint64_t) - 1LL) ||
246       (duration.value == (uint64_t) - 1LL))
247     return GNUNET_TIME_absolute_get_forever ();
248   if (start.value + duration.value < start.value)
249     {
250       GNUNET_break (0);
251       return GNUNET_TIME_absolute_get_forever ();
252     }
253   ret.value = start.value + duration.value;
254   return ret;
255 }
256
257 /**
258  * Multiply relative time by a given factor.
259  *
260  * @return FOREVER if rel=FOREVER or on overflow; otherwise rel*factor
261  */
262 struct GNUNET_TIME_Relative
263 GNUNET_TIME_relative_multiply (struct GNUNET_TIME_Relative rel,
264                                unsigned int factor)
265 {
266   struct GNUNET_TIME_Relative ret;
267   if (factor == 0)
268     return GNUNET_TIME_relative_get_zero ();
269   ret.value = rel.value * (unsigned long long) factor;
270   if (ret.value / factor != rel.value)
271     {
272       GNUNET_break (0);
273       return GNUNET_TIME_relative_get_forever ();
274     }
275   return ret;
276 }
277
278
279 /**
280  * Calculate the estimate time of arrival/completion 
281  * for an operation.
282  *
283  * @param start when did the operation start?
284  * @param finished how much has been done?
285  * @param total how much must be done overall (same unit as for "finished")
286  * @return remaining duration for the operation,
287  *        assuming it continues at the same speed
288  */
289 struct GNUNET_TIME_Relative
290 GNUNET_TIME_calculate_eta (struct GNUNET_TIME_Absolute start,
291                            uint64_t finished, uint64_t total)
292 {
293   struct GNUNET_TIME_Relative dur;
294   double exp;
295   struct GNUNET_TIME_Relative ret;
296
297   GNUNET_break (finished <= total);
298   if (finished >= total)
299     return GNUNET_TIME_UNIT_ZERO;
300   if (finished == 0)
301     return GNUNET_TIME_UNIT_FOREVER_REL;
302   dur = GNUNET_TIME_absolute_get_duration (start);
303   exp = ((double) dur.value) * ((double) total) / ((double) finished);
304   ret.value = ((uint64_t) exp) - dur.value;
305   return ret;
306 }
307
308
309 /**
310  * Add relative times together.
311  *
312  * @return FOREVER if either argument is FOREVER or on overflow; a1+a2 otherwise
313  */
314 struct GNUNET_TIME_Relative
315 GNUNET_TIME_relative_add (struct GNUNET_TIME_Relative a1,
316                           struct GNUNET_TIME_Relative a2)
317 {
318   struct GNUNET_TIME_Relative ret;
319
320   if ((a1.value == (uint64_t) - 1LL) || (a2.value == (uint64_t) - 1LL))
321     return GNUNET_TIME_relative_get_forever ();
322   if (a1.value + a2.value < a1.value)
323     {
324       GNUNET_break (0);
325       return GNUNET_TIME_relative_get_forever ();
326     }
327   ret.value = a1.value + a2.value;
328   return ret;
329 }
330
331
332 /**
333  * Convert relative time to network byte order.
334  */
335 struct GNUNET_TIME_RelativeNBO
336 GNUNET_TIME_relative_hton (struct GNUNET_TIME_Relative a)
337 {
338   struct GNUNET_TIME_RelativeNBO ret;
339   ret.value__ = GNUNET_htonll (a.value);
340   return ret;
341 }
342
343 /**
344  * Convert relative time from network byte order.
345  */
346 struct GNUNET_TIME_Relative
347 GNUNET_TIME_relative_ntoh (struct GNUNET_TIME_RelativeNBO a)
348 {
349   struct GNUNET_TIME_Relative ret;
350   ret.value = GNUNET_ntohll (a.value__);
351   return ret;
352
353 }
354
355 /**
356  * Convert absolute time to network byte order.
357  */
358 struct GNUNET_TIME_AbsoluteNBO
359 GNUNET_TIME_absolute_hton (struct GNUNET_TIME_Absolute a)
360 {
361   struct GNUNET_TIME_AbsoluteNBO ret;
362   ret.value__ = GNUNET_htonll (a.value);
363   return ret;
364 }
365
366 /**
367  * Convert absolute time from network byte order.
368  */
369 struct GNUNET_TIME_Absolute
370 GNUNET_TIME_absolute_ntoh (struct GNUNET_TIME_AbsoluteNBO a)
371 {
372   struct GNUNET_TIME_Absolute ret;
373   ret.value = GNUNET_ntohll (a.value__);
374   return ret;
375
376 }
377
378
379
380 /* end of time.c */