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