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