keepalive PINGs
[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  * Return the maximum of two relative time values.
142  *
143  * @param t1 first timestamp
144  * @param t2 other timestamp
145  * @return timestamp that is larger
146  */
147 struct GNUNET_TIME_Relative
148 GNUNET_TIME_relative_max (struct
149                           GNUNET_TIME_Relative
150                           t1, struct GNUNET_TIME_Relative t2)
151 {
152   return (t1.value > t2.value) ? t1 : t2;
153 }
154
155
156
157 /**
158  * Return the minimum 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_min (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  * Return the maximum of two relative time values.
175  *
176  * @param t1 first timestamp
177  * @param t2 other timestamp
178  * @return timestamp that is smaller
179  */
180 struct GNUNET_TIME_Absolute
181 GNUNET_TIME_absolute_max (struct
182                           GNUNET_TIME_Absolute
183                           t1, struct GNUNET_TIME_Absolute t2)
184 {
185   return (t1.value > t2.value) ? t1 : t2;
186 }
187
188
189 /**
190  * Given a timestamp in the future, how much time
191  * remains until then?
192  *
193  * @return future - now, or 0 if now >= future, or FOREVER if future==FOREVER.
194  */
195 struct GNUNET_TIME_Relative
196 GNUNET_TIME_absolute_get_remaining (struct GNUNET_TIME_Absolute future)
197 {
198   struct GNUNET_TIME_Relative ret;
199   if (future.value == (uint64_t) - 1LL)
200     return GNUNET_TIME_relative_get_forever ();
201   struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
202   if (now.value > future.value)
203     return GNUNET_TIME_relative_get_zero ();
204   ret.value = future.value - now.value;
205   return ret;
206 }
207
208 /**
209  * Compute the time difference between the given start and end times.
210  * Use this function instead of actual subtraction to ensure that
211  * "FOREVER" and overflows are handeled correctly.
212  *
213  * @return 0 if start >= end; FOREVER if end==FOREVER; otherwise end - start
214  */
215 struct GNUNET_TIME_Relative
216 GNUNET_TIME_absolute_get_difference (struct GNUNET_TIME_Absolute start,
217                                      struct GNUNET_TIME_Absolute end)
218 {
219   struct GNUNET_TIME_Relative ret;
220   if (end.value == (uint64_t) - 1LL)
221     return GNUNET_TIME_relative_get_forever ();
222   if (end.value < start.value)
223     return GNUNET_TIME_relative_get_zero ();
224   ret.value = end.value - start.value;
225   return ret;
226 }
227
228 /**
229  * Get the duration of an operation as the
230  * difference of the current time and the given start time "hence".
231  *
232  * @return aborts if hence==FOREVER, 0 if hence > now, otherwise now-hence.
233  */
234 struct GNUNET_TIME_Relative
235 GNUNET_TIME_absolute_get_duration (struct GNUNET_TIME_Absolute hence)
236 {
237   struct GNUNET_TIME_Absolute now;
238   struct GNUNET_TIME_Relative ret;
239
240   now = GNUNET_TIME_absolute_get ();
241   GNUNET_assert (hence.value != (uint64_t) - 1LL);
242   if (hence.value > now.value)
243     return GNUNET_TIME_relative_get_zero ();
244   ret.value = now.value - hence.value;
245   return ret;
246 }
247
248
249 /**
250  * Add a given relative duration to the
251  * given start time.
252  *
253  * @return FOREVER if either argument is FOREVER or on overflow; start+duration otherwise
254  */
255 struct GNUNET_TIME_Absolute
256 GNUNET_TIME_absolute_add (struct GNUNET_TIME_Absolute start,
257                           struct GNUNET_TIME_Relative duration)
258 {
259   struct GNUNET_TIME_Absolute ret;
260
261   if ((start.value == (uint64_t) - 1LL) ||
262       (duration.value == (uint64_t) - 1LL))
263     return GNUNET_TIME_absolute_get_forever ();
264   if (start.value + duration.value < start.value)
265     {
266       GNUNET_break (0);
267       return GNUNET_TIME_absolute_get_forever ();
268     }
269   ret.value = start.value + duration.value;
270   return ret;
271 }
272
273 /**
274  * Multiply relative time by a given factor.
275  *
276  * @return FOREVER if rel=FOREVER or on overflow; otherwise rel*factor
277  */
278 struct GNUNET_TIME_Relative
279 GNUNET_TIME_relative_multiply (struct GNUNET_TIME_Relative rel,
280                                unsigned int factor)
281 {
282   struct GNUNET_TIME_Relative ret;
283   if (factor == 0)
284     return GNUNET_TIME_relative_get_zero ();
285   ret.value = rel.value * (unsigned long long) factor;
286   if (ret.value / factor != rel.value)
287     {
288       GNUNET_break (0);
289       return GNUNET_TIME_relative_get_forever ();
290     }
291   return ret;
292 }
293
294
295 /**
296  * Divide relative time by a given factor.
297  *
298  * @param rel some duration
299  * @param factor integer to divide by
300  * @return FOREVER if rel=FOREVER or factor==0; otherwise rel/factor
301  */
302 struct GNUNET_TIME_Relative
303 GNUNET_TIME_relative_divide (struct GNUNET_TIME_Relative rel,
304                              unsigned int factor)
305 {
306   struct GNUNET_TIME_Relative ret;
307   if ( (factor == 0) ||
308        (rel.value == GNUNET_TIME_UNIT_FOREVER_REL.value) )
309     return GNUNET_TIME_UNIT_FOREVER_REL;
310   ret.value = rel.value / (unsigned long long) factor;
311   return ret;
312 }
313
314
315 /**
316  * Calculate the estimate time of arrival/completion 
317  * for an operation.
318  *
319  * @param start when did the operation start?
320  * @param finished how much has been done?
321  * @param total how much must be done overall (same unit as for "finished")
322  * @return remaining duration for the operation,
323  *        assuming it continues at the same speed
324  */
325 struct GNUNET_TIME_Relative
326 GNUNET_TIME_calculate_eta (struct GNUNET_TIME_Absolute start,
327                            uint64_t finished, uint64_t total)
328 {
329   struct GNUNET_TIME_Relative dur;
330   double exp;
331   struct GNUNET_TIME_Relative ret;
332
333   GNUNET_break (finished <= total);
334   if (finished >= total)
335     return GNUNET_TIME_UNIT_ZERO;
336   if (finished == 0)
337     return GNUNET_TIME_UNIT_FOREVER_REL;
338   dur = GNUNET_TIME_absolute_get_duration (start);
339   exp = ((double) dur.value) * ((double) total) / ((double) finished);
340   ret.value = ((uint64_t) exp) - dur.value;
341   return ret;
342 }
343
344
345 /**
346  * Add relative times together.
347  *
348  * @return FOREVER if either argument is FOREVER or on overflow; a1+a2 otherwise
349  */
350 struct GNUNET_TIME_Relative
351 GNUNET_TIME_relative_add (struct GNUNET_TIME_Relative a1,
352                           struct GNUNET_TIME_Relative a2)
353 {
354   struct GNUNET_TIME_Relative ret;
355
356   if ((a1.value == (uint64_t) - 1LL) || (a2.value == (uint64_t) - 1LL))
357     return GNUNET_TIME_relative_get_forever ();
358   if (a1.value + a2.value < a1.value)
359     {
360       GNUNET_break (0);
361       return GNUNET_TIME_relative_get_forever ();
362     }
363   ret.value = a1.value + a2.value;
364   return ret;
365 }
366
367
368 /**
369  * Convert relative time to network byte order.
370  */
371 struct GNUNET_TIME_RelativeNBO
372 GNUNET_TIME_relative_hton (struct GNUNET_TIME_Relative a)
373 {
374   struct GNUNET_TIME_RelativeNBO ret;
375   ret.value__ = GNUNET_htonll (a.value);
376   return ret;
377 }
378
379 /**
380  * Convert relative time from network byte order.
381  */
382 struct GNUNET_TIME_Relative
383 GNUNET_TIME_relative_ntoh (struct GNUNET_TIME_RelativeNBO a)
384 {
385   struct GNUNET_TIME_Relative ret;
386   ret.value = GNUNET_ntohll (a.value__);
387   return ret;
388
389 }
390
391 /**
392  * Convert absolute time to network byte order.
393  */
394 struct GNUNET_TIME_AbsoluteNBO
395 GNUNET_TIME_absolute_hton (struct GNUNET_TIME_Absolute a)
396 {
397   struct GNUNET_TIME_AbsoluteNBO ret;
398   ret.value__ = GNUNET_htonll (a.value);
399   return ret;
400 }
401
402 /**
403  * Convert absolute time from network byte order.
404  */
405 struct GNUNET_TIME_Absolute
406 GNUNET_TIME_absolute_ntoh (struct GNUNET_TIME_AbsoluteNBO a)
407 {
408   struct GNUNET_TIME_Absolute ret;
409   ret.value = GNUNET_ntohll (a.value__);
410   return ret;
411
412 }
413
414
415
416 /* end of time.c */