comments
[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 static long long timestamp_offset;
30
31 /**
32  * Set the timestamp offset for this instance.
33  *
34  * @param offset the offset to skew the locale time by
35  */
36 void
37 GNUNET_TIME_set_offset(long long offset)
38 {
39   timestamp_offset = offset;
40 }
41
42 /**
43  * Get the current time (works just as "time", just that we use the
44  * unit of time that the cron-jobs use (and is 64 bit)).
45  *
46  * @return the current time
47  */
48 struct GNUNET_TIME_Absolute
49 GNUNET_TIME_absolute_get ()
50 {
51   struct GNUNET_TIME_Absolute ret;
52   struct timeval tv;
53
54   GETTIMEOFDAY (&tv, NULL);
55   ret.abs_value =
56     (uint64_t) (((uint64_t) tv.tv_sec * 1000LL) +
57                 ((uint64_t) tv.tv_usec / 1000LL)) + timestamp_offset;
58   return ret;
59 }
60
61
62 /**
63  * Return relative time of 0ms.
64  */
65 struct GNUNET_TIME_Relative
66 GNUNET_TIME_relative_get_zero ()
67 {
68   static struct GNUNET_TIME_Relative zero;
69   return zero;
70 }
71
72
73 /**
74  * Return absolute time of 0ms.
75  */
76 struct GNUNET_TIME_Absolute
77 GNUNET_TIME_absolute_get_zero ()
78 {
79   static struct GNUNET_TIME_Absolute zero;
80   return zero;
81 }
82
83 /**
84  * Return relative time of 1ms.
85  */
86 struct GNUNET_TIME_Relative
87 GNUNET_TIME_relative_get_unit ()
88 {
89   static struct GNUNET_TIME_Relative one = { 1 };
90   return one;
91 }
92
93 /**
94  * Return "forever".
95  */
96 struct GNUNET_TIME_Relative
97 GNUNET_TIME_relative_get_forever ()
98 {
99   static struct GNUNET_TIME_Relative forever = { UINT64_MAX };
100   return forever;
101 }
102
103 /**
104  * Return "forever".
105  */
106 struct GNUNET_TIME_Absolute
107 GNUNET_TIME_absolute_get_forever ()
108 {
109   static struct GNUNET_TIME_Absolute forever = { UINT64_MAX };
110   return forever;
111 }
112
113 /**
114  * Convert relative time to an absolute time in the
115  * future.
116  *
117  * @return timestamp that is "rel" in the future, or FOREVER if rel==FOREVER (or if we would overflow)
118  */
119 struct GNUNET_TIME_Absolute
120 GNUNET_TIME_relative_to_absolute (struct GNUNET_TIME_Relative rel)
121 {
122   struct GNUNET_TIME_Absolute ret;
123   if (rel.rel_value == UINT64_MAX)
124     return GNUNET_TIME_absolute_get_forever ();
125   struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
126   if (rel.rel_value + now.abs_value < rel.rel_value)
127     {
128       GNUNET_break (0);         /* overflow... */
129       return GNUNET_TIME_absolute_get_forever ();
130     }
131   ret.abs_value = rel.rel_value + now.abs_value;
132   return ret;
133 }
134
135
136 /**
137  * Return the minimum of two relative time values.
138  *
139  * @param t1 first timestamp
140  * @param t2 other timestamp
141  * @return timestamp that is smaller
142  */
143 struct GNUNET_TIME_Relative
144 GNUNET_TIME_relative_min (struct
145                           GNUNET_TIME_Relative
146                           t1, struct GNUNET_TIME_Relative t2)
147 {
148   return (t1.rel_value < t2.rel_value) ? t1 : t2;
149 }
150
151
152 /**
153  * Return the maximum of two relative time values.
154  *
155  * @param t1 first timestamp
156  * @param t2 other timestamp
157  * @return timestamp that is larger
158  */
159 struct GNUNET_TIME_Relative
160 GNUNET_TIME_relative_max (struct
161                           GNUNET_TIME_Relative
162                           t1, struct GNUNET_TIME_Relative t2)
163 {
164   return (t1.rel_value > t2.rel_value) ? t1 : t2;
165 }
166
167
168
169 /**
170  * Return the minimum of two relative time values.
171  *
172  * @param t1 first timestamp
173  * @param t2 other timestamp
174  * @return timestamp that is smaller
175  */
176 struct GNUNET_TIME_Absolute
177 GNUNET_TIME_absolute_min (struct
178                           GNUNET_TIME_Absolute
179                           t1, struct GNUNET_TIME_Absolute t2)
180 {
181   return (t1.abs_value < t2.abs_value) ? t1 : t2;
182 }
183
184
185 /**
186  * Return the maximum of two relative time values.
187  *
188  * @param t1 first timestamp
189  * @param t2 other timestamp
190  * @return timestamp that is smaller
191  */
192 struct GNUNET_TIME_Absolute
193 GNUNET_TIME_absolute_max (struct
194                           GNUNET_TIME_Absolute
195                           t1, struct GNUNET_TIME_Absolute t2)
196 {
197   return (t1.abs_value > t2.abs_value) ? t1 : t2;
198 }
199
200
201 /**
202  * Given a timestamp in the future, how much time
203  * remains until then?
204  *
205  * @return future - now, or 0 if now >= future, or FOREVER if future==FOREVER.
206  */
207 struct GNUNET_TIME_Relative
208 GNUNET_TIME_absolute_get_remaining (struct GNUNET_TIME_Absolute future)
209 {
210   struct GNUNET_TIME_Relative ret;
211   if (future.abs_value == UINT64_MAX)
212     return GNUNET_TIME_relative_get_forever ();
213   struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
214   if (now.abs_value > future.abs_value)
215     return GNUNET_TIME_relative_get_zero ();
216   ret.rel_value = future.abs_value - now.abs_value;
217   return ret;
218 }
219
220 /**
221  * Compute the time difference between the given start and end times.
222  * Use this function instead of actual subtraction to ensure that
223  * "FOREVER" and overflows are handled correctly.
224  *
225  * @return 0 if start >= end; FOREVER if end==FOREVER; otherwise end - start
226  */
227 struct GNUNET_TIME_Relative
228 GNUNET_TIME_absolute_get_difference (struct GNUNET_TIME_Absolute start,
229                                      struct GNUNET_TIME_Absolute end)
230 {
231   struct GNUNET_TIME_Relative ret;
232   if (end.abs_value == UINT64_MAX)
233     return GNUNET_TIME_relative_get_forever ();
234   if (end.abs_value < start.abs_value)
235     return GNUNET_TIME_relative_get_zero ();
236   ret.rel_value = end.abs_value - start.abs_value;
237   return ret;
238 }
239
240 /**
241  * Get the duration of an operation as the
242  * difference of the current time and the given start time "whence".
243  *
244  * @return aborts if whence==FOREVER, 0 if whence > now, otherwise now-whence.
245  */
246 struct GNUNET_TIME_Relative
247 GNUNET_TIME_absolute_get_duration (struct GNUNET_TIME_Absolute whence)
248 {
249   struct GNUNET_TIME_Absolute now;
250   struct GNUNET_TIME_Relative ret;
251
252   now = GNUNET_TIME_absolute_get ();
253   GNUNET_assert (whence.abs_value != UINT64_MAX);
254   if (whence.abs_value > now.abs_value)
255     return GNUNET_TIME_relative_get_zero ();
256   ret.rel_value = now.abs_value - whence.abs_value;
257   return ret;
258 }
259
260
261 /**
262  * Add a given relative duration to the
263  * given start time.
264  *
265  * @return FOREVER if either argument is FOREVER or on overflow; start+duration otherwise
266  */
267 struct GNUNET_TIME_Absolute
268 GNUNET_TIME_absolute_add (struct GNUNET_TIME_Absolute start,
269                           struct GNUNET_TIME_Relative duration)
270 {
271   struct GNUNET_TIME_Absolute ret;
272
273   if ((start.abs_value == UINT64_MAX) ||
274       (duration.rel_value == UINT64_MAX))
275     return GNUNET_TIME_absolute_get_forever ();
276   if (start.abs_value + duration.rel_value < start.abs_value)
277     {
278       GNUNET_break (0);
279       return GNUNET_TIME_absolute_get_forever ();
280     }
281   ret.abs_value = start.abs_value + duration.rel_value;
282   return ret;
283 }
284
285
286 /**
287  * Subtract a given relative duration from the
288  * given start time.
289  *
290  * @param start some absolute time
291  * @param duration some relative time to subtract
292  * @return ZERO if start <= duration, or FOREVER if start time is FOREVER; start-duration otherwise
293  */
294 struct GNUNET_TIME_Absolute 
295 GNUNET_TIME_absolute_subtract (struct
296                                GNUNET_TIME_Absolute
297                                start,
298                                struct
299                                GNUNET_TIME_Relative
300                                duration)
301 {
302   struct GNUNET_TIME_Absolute ret;
303   if (start.abs_value <= duration.rel_value)
304     return GNUNET_TIME_UNIT_ZERO_ABS;
305   if (start.abs_value == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value)
306     return GNUNET_TIME_UNIT_FOREVER_ABS;
307   ret.abs_value = start.abs_value - duration.rel_value;
308   return ret;
309 }
310
311
312 /**
313  * Multiply relative time by a given factor.
314  *
315  * @return FOREVER if rel=FOREVER or on overflow; otherwise rel*factor
316  */
317 struct GNUNET_TIME_Relative
318 GNUNET_TIME_relative_multiply (struct GNUNET_TIME_Relative rel,
319                                unsigned int factor)
320 {
321   struct GNUNET_TIME_Relative ret;
322   if (factor == 0)
323     return GNUNET_TIME_relative_get_zero ();
324   ret.rel_value = rel.rel_value * (unsigned long long) factor;
325   if (ret.rel_value / factor != rel.rel_value)
326     {
327       GNUNET_break (0);
328       return GNUNET_TIME_relative_get_forever ();
329     }
330   return ret;
331 }
332
333
334 /**
335  * Divide relative time by a given factor.
336  *
337  * @param rel some duration
338  * @param factor integer to divide by
339  * @return FOREVER if rel=FOREVER or factor==0; otherwise rel/factor
340  */
341 struct GNUNET_TIME_Relative
342 GNUNET_TIME_relative_divide (struct GNUNET_TIME_Relative rel,
343                              unsigned int factor)
344 {
345   struct GNUNET_TIME_Relative ret;
346   if ( (factor == 0) ||
347        (rel.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value) )
348     return GNUNET_TIME_UNIT_FOREVER_REL;
349   ret.rel_value = rel.rel_value / (unsigned long long) factor;
350   return ret;
351 }
352
353
354 /**
355  * Calculate the estimate time of arrival/completion 
356  * for an operation.
357  *
358  * @param start when did the operation start?
359  * @param finished how much has been done?
360  * @param total how much must be done overall (same unit as for "finished")
361  * @return remaining duration for the operation,
362  *        assuming it continues at the same speed
363  */
364 struct GNUNET_TIME_Relative
365 GNUNET_TIME_calculate_eta (struct GNUNET_TIME_Absolute start,
366                            uint64_t finished, uint64_t total)
367 {
368   struct GNUNET_TIME_Relative dur;
369   double exp;
370   struct GNUNET_TIME_Relative ret;
371
372   GNUNET_break (finished <= total);
373   if (finished >= total)
374     return GNUNET_TIME_UNIT_ZERO;
375   if (finished == 0)
376     return GNUNET_TIME_UNIT_FOREVER_REL;
377   dur = GNUNET_TIME_absolute_get_duration (start);
378   exp = ((double) dur.rel_value) * ((double) total) / ((double) finished);
379   ret.rel_value = ((uint64_t) exp) - dur.rel_value;
380   return ret;
381 }
382
383
384 /**
385  * Add relative times together.
386  *
387  * @param a1 first timestamp
388  * @param a2 second timestamp
389  * @return FOREVER if either argument is FOREVER or on overflow; a1+a2 otherwise
390  */
391 struct GNUNET_TIME_Relative
392 GNUNET_TIME_relative_add (struct GNUNET_TIME_Relative a1,
393                           struct GNUNET_TIME_Relative a2)
394 {
395   struct GNUNET_TIME_Relative ret;
396
397   if ((a1.rel_value == UINT64_MAX) || (a2.rel_value == UINT64_MAX))
398     return GNUNET_TIME_relative_get_forever ();
399   if (a1.rel_value + a2.rel_value < a1.rel_value)
400     {
401       GNUNET_break (0);
402       return GNUNET_TIME_relative_get_forever ();
403     }
404   ret.rel_value = a1.rel_value + a2.rel_value;
405   return ret;
406 }
407
408
409 /**
410  * Subtract relative timestamp from the other.
411  *
412  * @param a1 first timestamp
413  * @param a2 second timestamp
414  * @return ZERO if a2>=a1 (including both FOREVER), FOREVER if a1 is FOREVER, a1-a2 otherwise
415  */
416 struct GNUNET_TIME_Relative
417 GNUNET_TIME_relative_subtract (struct GNUNET_TIME_Relative a1,
418                                struct GNUNET_TIME_Relative a2)
419 {
420   struct GNUNET_TIME_Relative ret;
421
422   if (a2.rel_value >= a1.rel_value)
423     return GNUNET_TIME_relative_get_zero ();
424   if (a1.rel_value == UINT64_MAX) 
425     return GNUNET_TIME_relative_get_forever ();
426   ret.rel_value = a1.rel_value - a2.rel_value;
427   return ret;
428 }
429
430
431 /**
432  * Convert relative time to network byte order.
433  *
434  * @param a time to convert
435  * @return time in network byte order
436  */
437 struct GNUNET_TIME_RelativeNBO
438 GNUNET_TIME_relative_hton (struct GNUNET_TIME_Relative a)
439 {
440   struct GNUNET_TIME_RelativeNBO ret;
441   ret.rel_value__ = GNUNET_htonll (a.rel_value);
442   return ret;
443 }
444
445 /**
446  * Convert relative time from network byte order.
447  *
448  * @param a time to convert
449  * @return time in host byte order
450  */
451 struct GNUNET_TIME_Relative
452 GNUNET_TIME_relative_ntoh (struct GNUNET_TIME_RelativeNBO a)
453 {
454   struct GNUNET_TIME_Relative ret;
455   ret.rel_value = GNUNET_ntohll (a.rel_value__);
456   return ret;
457
458 }
459
460 /**
461  * Convert absolute time to network byte order.
462  *
463  * @param a time to convert
464  * @return time in network byte order
465  */
466 struct GNUNET_TIME_AbsoluteNBO
467 GNUNET_TIME_absolute_hton (struct GNUNET_TIME_Absolute a)
468 {
469   struct GNUNET_TIME_AbsoluteNBO ret;
470   ret.abs_value__ = GNUNET_htonll (a.abs_value);
471   return ret;
472 }
473
474 /**
475  * Convert absolute time from network byte order.
476  *
477  * @param a time to convert
478  * @return time in host byte order
479  */
480 struct GNUNET_TIME_Absolute
481 GNUNET_TIME_absolute_ntoh (struct GNUNET_TIME_AbsoluteNBO a)
482 {
483   struct GNUNET_TIME_Absolute ret;
484   ret.abs_value = GNUNET_ntohll (a.abs_value__);
485   return ret;
486
487 }
488
489
490
491 /* end of time.c */