add function to obtain monotonic time
[oweals/gnunet.git] / src / util / time.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2001-2013, 2018 GNUnet e.V.
4
5      GNUnet is free software: you can redistribute it and/or modify it
6      under the terms of the GNU Affero General Public License as published
7      by the Free Software Foundation, either version 3 of the License,
8      or (at your 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      Affero General Public License for more details.
14     
15      You should have received a copy of the GNU Affero General Public License
16      along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 /**
20  * @file util/time.c
21  * @author Christian Grothoff
22  * @brief functions for handling time and time arithmetic
23  */
24 #include "platform.h"
25 #include "gnunet_util_lib.h"
26
27 #define LOG(kind,...) GNUNET_log_from (kind, "util-time", __VA_ARGS__)
28
29 /**
30  * Variable used to simulate clock skew.  Used for testing, never in production.
31  */
32 static long long timestamp_offset;
33
34 /**
35  * Set the timestamp offset for this instance.
36  *
37  * @param offset the offset to skew the locale time by
38  */
39 void
40 GNUNET_TIME_set_offset (long long offset)
41 {
42   timestamp_offset = offset;
43 }
44
45
46 /**
47  * Get the timestamp offset for this instance.
48  *
49  * @return the offset we currently skew the locale time by
50  */
51 long long
52 GNUNET_TIME_get_offset ()
53 {
54   return timestamp_offset;
55 }
56
57
58 /**
59  * Round a time value so that it is suitable for transmission
60  * via JSON encodings.
61  *
62  * @param at time to round
63  * @return #GNUNET_OK if time was already rounded, #GNUNET_NO if
64  *         it was just now rounded
65  */
66 int
67 GNUNET_TIME_round_abs (struct GNUNET_TIME_Absolute *at)
68 {
69   if (at->abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us)
70     return GNUNET_OK;
71   if (0 == at->abs_value_us % 1000000)
72     return GNUNET_OK;
73   at->abs_value_us -= at->abs_value_us % 1000000;
74   return GNUNET_NO;
75 }
76
77
78 /**
79  * Round a time value so that it is suitable for transmission
80  * via JSON encodings.
81  *
82  * @param rt time to round
83  * @return #GNUNET_OK if time was already rounded, #GNUNET_NO if
84  *         it was just now rounded
85  */
86 int
87 GNUNET_TIME_round_rel (struct GNUNET_TIME_Relative *rt)
88 {
89   if (rt->rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
90     return GNUNET_OK;
91   if (0 == rt->rel_value_us % 1000000)
92     return GNUNET_OK;
93   rt->rel_value_us -= rt->rel_value_us % 1000000;
94   return GNUNET_NO;
95 }
96
97
98 /**
99  * Get the current time (works just as "time", just that we use the
100  * unit of time that the cron-jobs use (and is 64 bit)).
101  *
102  * @return the current time
103  */
104 struct GNUNET_TIME_Absolute
105 GNUNET_TIME_absolute_get ()
106 {
107   struct GNUNET_TIME_Absolute ret;
108   struct timeval tv;
109
110   GETTIMEOFDAY (&tv, NULL);
111   ret.abs_value_us =
112       (uint64_t) (((uint64_t) tv.tv_sec * 1000LL * 1000LL) +
113                   ((uint64_t) tv.tv_usec)) + timestamp_offset;
114   return ret;
115 }
116
117
118 /**
119  * Return relative time of 0ms.
120  */
121 struct GNUNET_TIME_Relative
122 GNUNET_TIME_relative_get_zero_ ()
123 {
124   static struct GNUNET_TIME_Relative zero;
125
126   return zero;
127 }
128
129
130 /**
131  * Return absolute time of 0ms.
132  */
133 struct GNUNET_TIME_Absolute
134 GNUNET_TIME_absolute_get_zero_ ()
135 {
136   static struct GNUNET_TIME_Absolute zero;
137
138   return zero;
139 }
140
141
142 /**
143  * Return relative time of 1us.
144  */
145 struct GNUNET_TIME_Relative
146 GNUNET_TIME_relative_get_unit_ ()
147 {
148   static struct GNUNET_TIME_Relative one = { 1 };
149
150   return one;
151 }
152
153
154 /**
155  * Return relative time of 1ms.
156  */
157 struct GNUNET_TIME_Relative
158 GNUNET_TIME_relative_get_millisecond_ ()
159 {
160   static struct GNUNET_TIME_Relative one = { 1000 };
161
162   return one;
163 }
164
165
166 /**
167  * Return relative time of 1s.
168  */
169 struct GNUNET_TIME_Relative
170 GNUNET_TIME_relative_get_second_ ()
171 {
172   static struct GNUNET_TIME_Relative one = { 1000 * 1000LL };
173
174   return one;
175 }
176
177
178 /**
179  * Return relative time of 1 minute.
180  */
181 struct GNUNET_TIME_Relative
182 GNUNET_TIME_relative_get_minute_ ()
183 {
184   static struct GNUNET_TIME_Relative one = { 60 * 1000 * 1000LL };
185
186   return one;
187 }
188
189
190 /**
191  * Return relative time of 1 hour.
192  */
193 struct GNUNET_TIME_Relative
194 GNUNET_TIME_relative_get_hour_ ()
195 {
196   static struct GNUNET_TIME_Relative one = { 60 * 60 * 1000 * 1000LL };
197
198   return one;
199 }
200
201
202 /**
203  * Return "forever".
204  */
205 struct GNUNET_TIME_Relative
206 GNUNET_TIME_relative_get_forever_ ()
207 {
208   static struct GNUNET_TIME_Relative forever = { UINT64_MAX };
209
210   return forever;
211 }
212
213
214 /**
215  * Return "forever".
216  */
217 struct GNUNET_TIME_Absolute
218 GNUNET_TIME_absolute_get_forever_ ()
219 {
220   static struct GNUNET_TIME_Absolute forever = { UINT64_MAX };
221   return forever;
222 }
223
224
225 /**
226  * Convert relative time to an absolute time in the
227  * future.
228  *
229  * @return timestamp that is "rel" in the future, or FOREVER if rel==FOREVER (or if we would overflow)
230  */
231 struct GNUNET_TIME_Absolute
232 GNUNET_TIME_relative_to_absolute (struct GNUNET_TIME_Relative rel)
233 {
234   struct GNUNET_TIME_Absolute ret;
235
236   if (rel.rel_value_us == UINT64_MAX)
237     return GNUNET_TIME_UNIT_FOREVER_ABS;
238   struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
239
240   if (rel.rel_value_us + now.abs_value_us < rel.rel_value_us)
241   {
242     GNUNET_break (0);           /* overflow... */
243     return GNUNET_TIME_UNIT_FOREVER_ABS;
244   }
245   ret.abs_value_us = rel.rel_value_us + now.abs_value_us;
246   return ret;
247 }
248
249
250 /**
251  * Return the minimum of two relative time values.
252  *
253  * @param t1 first timestamp
254  * @param t2 other timestamp
255  * @return timestamp that is smaller
256  */
257 struct GNUNET_TIME_Relative
258 GNUNET_TIME_relative_min (struct GNUNET_TIME_Relative t1,
259                           struct GNUNET_TIME_Relative t2)
260 {
261   return (t1.rel_value_us < t2.rel_value_us) ? t1 : t2;
262 }
263
264
265 /**
266  * Return the maximum of two relative time values.
267  *
268  * @param t1 first timestamp
269  * @param t2 other timestamp
270  * @return timestamp that is larger
271  */
272 struct GNUNET_TIME_Relative
273 GNUNET_TIME_relative_max (struct GNUNET_TIME_Relative t1,
274                           struct GNUNET_TIME_Relative t2)
275 {
276   return (t1.rel_value_us > t2.rel_value_us) ? t1 : t2;
277 }
278
279
280
281 /**
282  * Return the minimum of two relative time values.
283  *
284  * @param t1 first timestamp
285  * @param t2 other timestamp
286  * @return timestamp that is smaller
287  */
288 struct GNUNET_TIME_Absolute
289 GNUNET_TIME_absolute_min (struct GNUNET_TIME_Absolute t1,
290                           struct GNUNET_TIME_Absolute t2)
291 {
292   return (t1.abs_value_us < t2.abs_value_us) ? t1 : t2;
293 }
294
295
296 /**
297  * Return the maximum of two relative time values.
298  *
299  * @param t1 first timestamp
300  * @param t2 other timestamp
301  * @return timestamp that is bigger
302  */
303 struct GNUNET_TIME_Absolute
304 GNUNET_TIME_absolute_max (struct GNUNET_TIME_Absolute t1,
305                           struct GNUNET_TIME_Absolute t2)
306 {
307   return (t1.abs_value_us > t2.abs_value_us) ? t1 : t2;
308 }
309
310
311 /**
312  * Given a timestamp in the future, how much time
313  * remains until then?
314  *
315  * @return future - now, or 0 if now >= future, or FOREVER if future==FOREVER.
316  */
317 struct GNUNET_TIME_Relative
318 GNUNET_TIME_absolute_get_remaining (struct GNUNET_TIME_Absolute future)
319 {
320   struct GNUNET_TIME_Relative ret;
321
322   if (future.abs_value_us == UINT64_MAX)
323     return GNUNET_TIME_UNIT_FOREVER_REL;
324   struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
325
326   if (now.abs_value_us > future.abs_value_us)
327     return GNUNET_TIME_UNIT_ZERO;
328   ret.rel_value_us = future.abs_value_us - now.abs_value_us;
329   return ret;
330 }
331
332 /**
333  * Compute the time difference between the given start and end times.
334  * Use this function instead of actual subtraction to ensure that
335  * "FOREVER" and overflows are handled correctly.
336  *
337  * @return 0 if start >= end; FOREVER if end==FOREVER; otherwise end - start
338  */
339 struct GNUNET_TIME_Relative
340 GNUNET_TIME_absolute_get_difference (struct GNUNET_TIME_Absolute start,
341                                      struct GNUNET_TIME_Absolute end)
342 {
343   struct GNUNET_TIME_Relative ret;
344
345   if (end.abs_value_us == UINT64_MAX)
346     return GNUNET_TIME_UNIT_FOREVER_REL;
347   if (end.abs_value_us < start.abs_value_us)
348     return GNUNET_TIME_UNIT_ZERO;
349   ret.rel_value_us = end.abs_value_us - start.abs_value_us;
350   return ret;
351 }
352
353 /**
354  * Get the duration of an operation as the
355  * difference of the current time and the given start time "whence".
356  *
357  * @return 0 if whence > now, otherwise now-whence.
358  */
359 struct GNUNET_TIME_Relative
360 GNUNET_TIME_absolute_get_duration (struct GNUNET_TIME_Absolute whence)
361 {
362   struct GNUNET_TIME_Absolute now;
363   struct GNUNET_TIME_Relative ret;
364
365   now = GNUNET_TIME_absolute_get ();
366   if (whence.abs_value_us > now.abs_value_us)
367     return GNUNET_TIME_UNIT_ZERO;
368   ret.rel_value_us = now.abs_value_us - whence.abs_value_us;
369   return ret;
370 }
371
372
373 /**
374  * Add a given relative duration to the
375  * given start time.
376  *
377  * @return FOREVER if either argument is FOREVER or on overflow; start+duration otherwise
378  */
379 struct GNUNET_TIME_Absolute
380 GNUNET_TIME_absolute_add (struct GNUNET_TIME_Absolute start,
381                           struct GNUNET_TIME_Relative duration)
382 {
383   struct GNUNET_TIME_Absolute ret;
384
385   if ((start.abs_value_us == UINT64_MAX) || (duration.rel_value_us == UINT64_MAX))
386     return GNUNET_TIME_UNIT_FOREVER_ABS;
387   if (start.abs_value_us + duration.rel_value_us < start.abs_value_us)
388   {
389     GNUNET_break (0);
390     return GNUNET_TIME_UNIT_FOREVER_ABS;
391   }
392   ret.abs_value_us = start.abs_value_us + duration.rel_value_us;
393   return ret;
394 }
395
396
397 /**
398  * Subtract a given relative duration from the
399  * given start time.
400  *
401  * @param start some absolute time
402  * @param duration some relative time to subtract
403  * @return ZERO if start <= duration, or FOREVER if start time is FOREVER; start-duration otherwise
404  */
405 struct GNUNET_TIME_Absolute
406 GNUNET_TIME_absolute_subtract (struct GNUNET_TIME_Absolute start,
407                                struct GNUNET_TIME_Relative duration)
408 {
409   struct GNUNET_TIME_Absolute ret;
410
411   if (start.abs_value_us <= duration.rel_value_us)
412     return GNUNET_TIME_UNIT_ZERO_ABS;
413   if (start.abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us)
414     return GNUNET_TIME_UNIT_FOREVER_ABS;
415   ret.abs_value_us = start.abs_value_us - duration.rel_value_us;
416   return ret;
417 }
418
419
420 /**
421  * Multiply relative time by a given factor.
422  *
423  * @return FOREVER if rel=FOREVER or on overflow; otherwise rel*factor
424  */
425 struct GNUNET_TIME_Relative
426 GNUNET_TIME_relative_multiply (struct GNUNET_TIME_Relative rel,
427                                unsigned long long factor)
428 {
429   struct GNUNET_TIME_Relative ret;
430
431   if (0 == factor)
432     return GNUNET_TIME_UNIT_ZERO;
433   if (rel.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
434     return GNUNET_TIME_UNIT_FOREVER_REL;
435   ret.rel_value_us = rel.rel_value_us * factor;
436   if (ret.rel_value_us / factor != rel.rel_value_us)
437   {
438     GNUNET_break (0);
439     return GNUNET_TIME_UNIT_FOREVER_REL;
440   }
441   return ret;
442 }
443
444
445 /**
446  * Multiply relative time by a given floating-point factor.  The factor must be
447  * positive.
448  *
449  * @return FOREVER if rel=FOREVER or on overflow; otherwise rel*factor
450  */
451 struct GNUNET_TIME_Relative
452 relative_multiply_double (struct GNUNET_TIME_Relative rel,
453                           double factor)
454 {
455   struct GNUNET_TIME_Relative out;
456   double m;
457
458   GNUNET_assert (0 <= factor);
459
460   if (0 == factor)
461     return GNUNET_TIME_UNIT_ZERO;
462   if (rel.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
463     return GNUNET_TIME_UNIT_FOREVER_REL;
464
465   m = ((double) rel.rel_value_us) * factor;
466
467   if (m >= (double) (GNUNET_TIME_UNIT_FOREVER_REL).rel_value_us)
468   {
469     GNUNET_break (0);
470     return GNUNET_TIME_UNIT_FOREVER_REL;
471   }
472
473   out.rel_value_us = (uint64_t) m;
474   return out;
475 }
476
477
478 /**
479  * Saturating multiply relative time by a given factor.
480  *
481  * @param rel some duration
482  * @param factor integer to multiply with
483  * @return FOREVER if rel=FOREVER or on overflow; otherwise rel*factor
484  */
485 struct GNUNET_TIME_Relative
486 GNUNET_TIME_relative_saturating_multiply (struct GNUNET_TIME_Relative rel,
487                                           unsigned long long factor)
488 {
489   struct GNUNET_TIME_Relative ret;
490
491   if (0 == factor)
492     return GNUNET_TIME_UNIT_ZERO;
493   if (rel.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
494     return GNUNET_TIME_UNIT_FOREVER_REL;
495   ret.rel_value_us = rel.rel_value_us * factor;
496   if (ret.rel_value_us / factor != rel.rel_value_us)
497   {
498     return GNUNET_TIME_UNIT_FOREVER_REL;
499   }
500   return ret;
501 }
502
503
504 /**
505  * Divide relative time by a given factor.
506  *
507  * @param rel some duration
508  * @param factor integer to divide by
509  * @return FOREVER if rel=FOREVER or factor==0; otherwise rel/factor
510  */
511 struct GNUNET_TIME_Relative
512 GNUNET_TIME_relative_divide (struct GNUNET_TIME_Relative rel,
513                              unsigned long long factor)
514 {
515   struct GNUNET_TIME_Relative ret;
516
517   if ((0 == factor) ||
518       (rel.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us))
519     return GNUNET_TIME_UNIT_FOREVER_REL;
520   ret.rel_value_us = rel.rel_value_us / factor;
521   return ret;
522 }
523
524
525 /**
526  * Calculate the estimate time of arrival/completion
527  * for an operation.
528  *
529  * @param start when did the operation start?
530  * @param finished how much has been done?
531  * @param total how much must be done overall (same unit as for "finished")
532  * @return remaining duration for the operation,
533  *        assuming it continues at the same speed
534  */
535 struct GNUNET_TIME_Relative
536 GNUNET_TIME_calculate_eta (struct GNUNET_TIME_Absolute start, uint64_t finished,
537                            uint64_t total)
538 {
539   struct GNUNET_TIME_Relative dur;
540   double exp;
541   struct GNUNET_TIME_Relative ret;
542
543   GNUNET_break (finished <= total);
544   if (finished >= total)
545     return GNUNET_TIME_UNIT_ZERO;
546   if (0 == finished)
547     return GNUNET_TIME_UNIT_FOREVER_REL;
548   dur = GNUNET_TIME_absolute_get_duration (start);
549   exp = ((double) dur.rel_value_us) * ((double) total) / ((double) finished);
550   ret.rel_value_us = ((uint64_t) exp) - dur.rel_value_us;
551   return ret;
552 }
553
554
555 /**
556  * Add relative times together.
557  *
558  * @param a1 first timestamp
559  * @param a2 second timestamp
560  * @return FOREVER if either argument is FOREVER or on overflow; a1+a2 otherwise
561  */
562 struct GNUNET_TIME_Relative
563 GNUNET_TIME_relative_add (struct GNUNET_TIME_Relative a1,
564                           struct GNUNET_TIME_Relative a2)
565 {
566   struct GNUNET_TIME_Relative ret;
567
568   if ((a1.rel_value_us == UINT64_MAX) || (a2.rel_value_us == UINT64_MAX))
569     return GNUNET_TIME_UNIT_FOREVER_REL;
570   if (a1.rel_value_us + a2.rel_value_us < a1.rel_value_us)
571   {
572     GNUNET_break (0);
573     return GNUNET_TIME_UNIT_FOREVER_REL;
574   }
575   ret.rel_value_us = a1.rel_value_us + a2.rel_value_us;
576   return ret;
577 }
578
579
580 /**
581  * Subtract relative timestamp from the other.
582  *
583  * @param a1 first timestamp
584  * @param a2 second timestamp
585  * @return ZERO if a2>=a1 (including both FOREVER), FOREVER if a1 is FOREVER, a1-a2 otherwise
586  */
587 struct GNUNET_TIME_Relative
588 GNUNET_TIME_relative_subtract (struct GNUNET_TIME_Relative a1,
589                                struct GNUNET_TIME_Relative a2)
590 {
591   struct GNUNET_TIME_Relative ret;
592
593   if (a2.rel_value_us >= a1.rel_value_us)
594     return GNUNET_TIME_UNIT_ZERO;
595   if (a1.rel_value_us == UINT64_MAX)
596     return GNUNET_TIME_UNIT_FOREVER_REL;
597   ret.rel_value_us = a1.rel_value_us - a2.rel_value_us;
598   return ret;
599 }
600
601
602 /**
603  * Convert relative time to network byte order.
604  *
605  * @param a time to convert
606  * @return time in network byte order
607  */
608 struct GNUNET_TIME_RelativeNBO
609 GNUNET_TIME_relative_hton (struct GNUNET_TIME_Relative a)
610 {
611   struct GNUNET_TIME_RelativeNBO ret;
612
613   ret.rel_value_us__ = GNUNET_htonll (a.rel_value_us);
614   return ret;
615 }
616
617
618 /**
619  * Convert relative time from network byte order.
620  *
621  * @param a time to convert
622  * @return time in host byte order
623  */
624 struct GNUNET_TIME_Relative
625 GNUNET_TIME_relative_ntoh (struct GNUNET_TIME_RelativeNBO a)
626 {
627   struct GNUNET_TIME_Relative ret;
628
629   ret.rel_value_us = GNUNET_ntohll (a.rel_value_us__);
630   return ret;
631 }
632
633
634 /**
635  * Convert absolute time to network byte order.
636  *
637  * @param a time to convert
638  * @return time in network byte order
639  */
640 struct GNUNET_TIME_AbsoluteNBO
641 GNUNET_TIME_absolute_hton (struct GNUNET_TIME_Absolute a)
642 {
643   struct GNUNET_TIME_AbsoluteNBO ret;
644
645   ret.abs_value_us__ = GNUNET_htonll (a.abs_value_us);
646   return ret;
647 }
648
649
650 /**
651  * Convert absolute time from network byte order.
652  *
653  * @param a time to convert
654  * @return time in host byte order
655  */
656 struct GNUNET_TIME_Absolute
657 GNUNET_TIME_absolute_ntoh (struct GNUNET_TIME_AbsoluteNBO a)
658 {
659   struct GNUNET_TIME_Absolute ret;
660
661   ret.abs_value_us = GNUNET_ntohll (a.abs_value_us__);
662   return ret;
663
664 }
665
666
667 /**
668  * Return the current year (i.e. '2011').
669  */
670 unsigned int
671 GNUNET_TIME_get_current_year ()
672 {
673   time_t tp;
674   struct tm *t;
675
676   tp = time (NULL);
677   t = gmtime (&tp);
678   if (t == NULL)
679     return 0;
680   return t->tm_year + 1900;
681 }
682
683
684 /**
685  * Convert an expiration time to the respective year (rounds)
686  *
687  * @param at absolute time
688  * @return year a year (after 1970), 0 on error
689  */
690 unsigned int
691 GNUNET_TIME_time_to_year (struct GNUNET_TIME_Absolute at)
692 {
693   struct tm *t;
694   time_t tp;
695
696   tp = at.abs_value_us / 1000LL / 1000LL;    /* microseconds to seconds */
697   t = gmtime (&tp);
698   if (t == NULL)
699     return 0;
700   return t->tm_year + 1900;
701
702 }
703
704
705 /**
706  * Convert a year to an expiration time of January 1st of that year.
707  *
708  * @param year a year (after 1970, please ;-)).
709  * @return absolute time for January 1st of that year.
710  */
711 struct GNUNET_TIME_Absolute
712 GNUNET_TIME_year_to_time (unsigned int year)
713 {
714   struct GNUNET_TIME_Absolute ret;
715   time_t tp;
716   struct tm t;
717
718   memset (&t, 0, sizeof (t));
719   if (year < 1900)
720   {
721     GNUNET_break (0);
722     return GNUNET_TIME_absolute_get (); /* now */
723   }
724   t.tm_year = year - 1900;
725   t.tm_mday = 1;
726   t.tm_mon = 0;
727   t.tm_wday = 1;
728   t.tm_yday = 1;
729   tp = mktime (&t);
730   GNUNET_break (tp != (time_t) - 1);
731   ret.abs_value_us = tp * 1000LL * 1000LL;  /* seconds to microseconds */
732   return ret;
733 }
734
735
736 /**
737  * Randomized exponential back-off, starting at 1 ms
738  * and going up by a factor of 2+r, where 0 <= r <= 0.5, up
739  * to a maximum of the given threshold.
740  *
741  * @param r current backoff time, initially zero
742  * @param threshold maximum value for backoff
743  * @return the next backoff time
744  */
745 struct GNUNET_TIME_Relative
746 GNUNET_TIME_randomized_backoff(struct GNUNET_TIME_Relative rt, struct GNUNET_TIME_Relative threshold)
747 {
748   double r = (rand() % 500) / 1000.0;
749   struct GNUNET_TIME_Relative t;
750
751   t = relative_multiply_double (GNUNET_TIME_relative_max (GNUNET_TIME_UNIT_MILLISECONDS,
752                                                           rt),
753                                 2 + r);
754   return GNUNET_TIME_relative_min (threshold,
755                                    t);
756 }
757
758
759 /**
760  * Obtain the current time and make sure it is monotonically
761  * increasing.  Guards against systems without an RTC or
762  * clocks running backwards and other nasty surprises. Does
763  * not guarantee that the returned time is near the current
764  * time returned by #GNUNET_TIME_absolute_get().  Two 
765  * subsequent calls (within a short time period) may return the
766  * same value. Persists the last returned time on disk to
767  * ensure that time never goes backwards. As a result, the
768  * resulting value can be used to check if a message is the 
769  * "most recent" value and replays of older messages (from
770  * the same origin) would be discarded.
771  * 
772  * @param cfg configuration, used to determine where to 
773  *   store the time; user can also insist RTC is working
774  *   nicely and disable the feature
775  * @return monotonically increasing time
776  */
777 struct GNUNET_TIME_Absolute
778 GNUNET_TIME_absolute_get_monotonic (const struct GNUNET_CONFIGURATION_Handle *cfg)
779 {
780   static const struct GNUNET_CONFIGURATION_Handle *last_cfg;
781   static struct GNUNET_TIME_Absolute last_time;
782   static struct GNUNET_DISK_MapHandle *map_handle;
783   static struct GNUNET_TIME_AbsoluteNBO *map;
784   struct GNUNET_TIME_Absolute now;
785
786   now = GNUNET_TIME_absolute_get ();
787   if (last_cfg != cfg)
788   {
789     char *filename;
790
791     if (NULL != map_handle)
792     {
793       GNUNET_DISK_file_unmap (map_handle);
794       map_handle = NULL;
795     }
796     map = NULL;
797     
798     last_cfg = cfg;
799     if ( (NULL != cfg) &&
800          (GNUNET_OK ==
801           GNUNET_CONFIGURATION_get_value_filename (cfg,
802                                                    "util",
803                                                    "MONOTONIC_TIME_FILENAME",
804                                                    &filename)) )
805     {
806       struct GNUNET_DISK_FileHandle *fh;
807
808       fh = GNUNET_DISK_file_open (filename,
809                                   GNUNET_DISK_OPEN_READWRITE | GNUNET_DISK_OPEN_CREATE,
810                                   GNUNET_DISK_PERM_USER_WRITE | GNUNET_DISK_PERM_GROUP_WRITE |
811                                   GNUNET_DISK_PERM_USER_READ  | GNUNET_DISK_PERM_GROUP_READ);
812       if (NULL == fh)
813       {
814         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
815                     _("Failed to map `%s', cannot assure monotonic time!\n"),
816                     filename);
817       }
818       else
819       { 
820         off_t size;
821
822         size = 0;
823         GNUNET_break (GNUNET_OK ==
824                       GNUNET_DISK_file_handle_size (fh,
825                                                     &size));
826         if (size < sizeof (*map))
827         {
828           struct GNUNET_TIME_AbsoluteNBO o;
829
830           o = GNUNET_TIME_absolute_hton (now);
831           if (sizeof (o) !=
832               GNUNET_DISK_file_write (fh,
833                                       &o,
834                                       sizeof (o)))
835             size = 0;
836           else
837             size = sizeof (o);
838         }
839         if (size == sizeof (*map))
840         {
841           map = GNUNET_DISK_file_map (fh,
842                                       &map_handle,
843                                       GNUNET_DISK_MAP_TYPE_READWRITE,
844                                       sizeof (*map));
845           if (NULL == map)
846             GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
847                         _("Failed to map `%s', cannot assure monotonic time!\n"),
848                         filename);
849         }
850         else
851         {
852           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
853                       _("Failed to setup monotonic time file `%s', cannot assure monotonic time!\n"),
854                       filename);
855         }
856       }
857       GNUNET_DISK_file_close (fh);
858       GNUNET_free (filename);
859     }
860   }
861   if (NULL != map)
862     last_time = GNUNET_TIME_absolute_max (GNUNET_TIME_absolute_ntoh (*map),
863                                           last_time);
864   if (now.abs_value_us <= last_time.abs_value_us)
865     now.abs_value_us = last_time.abs_value_us+1;
866   last_time = now;
867   if (NULL != map)
868     *map = GNUNET_TIME_absolute_hton (now);
869   return now;
870 }
871
872
873 /**
874  * Destructor
875  */
876 void __attribute__ ((destructor))
877 GNUNET_util_time_fini ()
878 {
879   (void) GNUNET_TIME_absolute_get_monotonic (NULL);
880 }
881
882 /* end of time.c */