use NULL value in load_path_suffix to NOT load any files
[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 /**
347  * Compute the time difference between the given start and end times.
348  * Use this function instead of actual subtraction to ensure that
349  * "FOREVER" and overflows are handled correctly.
350  *
351  * @return 0 if start >= end; FOREVER if end==FOREVER; otherwise end - start
352  */
353 struct GNUNET_TIME_Relative
354 GNUNET_TIME_absolute_get_difference (struct GNUNET_TIME_Absolute start,
355                                      struct GNUNET_TIME_Absolute end)
356 {
357   struct GNUNET_TIME_Relative ret;
358
359   if (end.abs_value_us == UINT64_MAX)
360     return GNUNET_TIME_UNIT_FOREVER_REL;
361   if (end.abs_value_us < start.abs_value_us)
362     return GNUNET_TIME_UNIT_ZERO;
363   ret.rel_value_us = end.abs_value_us - start.abs_value_us;
364   return ret;
365 }
366
367
368 /**
369  * Get the duration of an operation as the
370  * difference of the current time and the given start time "whence".
371  *
372  * @return 0 if whence > now, otherwise now-whence.
373  */
374 struct GNUNET_TIME_Relative
375 GNUNET_TIME_absolute_get_duration (struct GNUNET_TIME_Absolute whence)
376 {
377   struct GNUNET_TIME_Absolute now;
378   struct GNUNET_TIME_Relative ret;
379
380   now = GNUNET_TIME_absolute_get ();
381   if (whence.abs_value_us > now.abs_value_us)
382     return GNUNET_TIME_UNIT_ZERO;
383   ret.rel_value_us = now.abs_value_us - whence.abs_value_us;
384   return ret;
385 }
386
387
388 /**
389  * Add a given relative duration to the
390  * given start time.
391  *
392  * @return FOREVER if either argument is FOREVER or on overflow; start+duration otherwise
393  */
394 struct GNUNET_TIME_Absolute
395 GNUNET_TIME_absolute_add (struct GNUNET_TIME_Absolute start,
396                           struct GNUNET_TIME_Relative duration)
397 {
398   struct GNUNET_TIME_Absolute ret;
399
400   if ((start.abs_value_us == UINT64_MAX) ||
401       (duration.rel_value_us == UINT64_MAX))
402     return GNUNET_TIME_UNIT_FOREVER_ABS;
403   if (start.abs_value_us + duration.rel_value_us < start.abs_value_us)
404   {
405     GNUNET_break (0);
406     return GNUNET_TIME_UNIT_FOREVER_ABS;
407   }
408   ret.abs_value_us = start.abs_value_us + duration.rel_value_us;
409   return ret;
410 }
411
412
413 /**
414  * Subtract a given relative duration from the
415  * given start time.
416  *
417  * @param start some absolute time
418  * @param duration some relative time to subtract
419  * @return ZERO if start <= duration, or FOREVER if start time is FOREVER; start-duration otherwise
420  */
421 struct GNUNET_TIME_Absolute
422 GNUNET_TIME_absolute_subtract (struct GNUNET_TIME_Absolute start,
423                                struct GNUNET_TIME_Relative duration)
424 {
425   struct GNUNET_TIME_Absolute ret;
426
427   if (start.abs_value_us <= duration.rel_value_us)
428     return GNUNET_TIME_UNIT_ZERO_ABS;
429   if (start.abs_value_us == GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us)
430     return GNUNET_TIME_UNIT_FOREVER_ABS;
431   ret.abs_value_us = start.abs_value_us - duration.rel_value_us;
432   return ret;
433 }
434
435
436 /**
437  * Multiply relative time by a given factor.
438  *
439  * @return FOREVER if rel=FOREVER or on overflow; otherwise rel*factor
440  */
441 struct GNUNET_TIME_Relative
442 GNUNET_TIME_relative_multiply (struct GNUNET_TIME_Relative rel,
443                                unsigned long long factor)
444 {
445   struct GNUNET_TIME_Relative ret;
446
447   if (0 == factor)
448     return GNUNET_TIME_UNIT_ZERO;
449   if (rel.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
450     return GNUNET_TIME_UNIT_FOREVER_REL;
451   ret.rel_value_us = rel.rel_value_us * factor;
452   if (ret.rel_value_us / factor != rel.rel_value_us)
453   {
454     GNUNET_break (0);
455     return GNUNET_TIME_UNIT_FOREVER_REL;
456   }
457   return ret;
458 }
459
460
461 /**
462  * Multiply relative time by a given floating-point factor.  The factor must be
463  * positive.
464  *
465  * @return FOREVER if rel=FOREVER or on overflow; otherwise rel*factor
466  */
467 struct GNUNET_TIME_Relative
468 relative_multiply_double (struct GNUNET_TIME_Relative rel, double factor)
469 {
470   struct GNUNET_TIME_Relative out;
471   double m;
472
473   GNUNET_assert (0 <= factor);
474
475   if (0 == factor)
476     return GNUNET_TIME_UNIT_ZERO;
477   if (rel.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
478     return GNUNET_TIME_UNIT_FOREVER_REL;
479
480   m = ((double) rel.rel_value_us) * factor;
481
482   if (m >= (double) (GNUNET_TIME_UNIT_FOREVER_REL).rel_value_us)
483   {
484     GNUNET_break (0);
485     return GNUNET_TIME_UNIT_FOREVER_REL;
486   }
487
488   out.rel_value_us = (uint64_t) m;
489   return out;
490 }
491
492
493 /**
494  * Saturating multiply relative time by a given factor.
495  *
496  * @param rel some duration
497  * @param factor integer to multiply with
498  * @return FOREVER if rel=FOREVER or on overflow; otherwise rel*factor
499  */
500 struct GNUNET_TIME_Relative
501 GNUNET_TIME_relative_saturating_multiply (struct GNUNET_TIME_Relative rel,
502                                           unsigned long long factor)
503 {
504   struct GNUNET_TIME_Relative ret;
505
506   if (0 == factor)
507     return GNUNET_TIME_UNIT_ZERO;
508   if (rel.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
509     return GNUNET_TIME_UNIT_FOREVER_REL;
510   ret.rel_value_us = rel.rel_value_us * factor;
511   if (ret.rel_value_us / factor != rel.rel_value_us)
512   {
513     return GNUNET_TIME_UNIT_FOREVER_REL;
514   }
515   return ret;
516 }
517
518
519 /**
520  * Divide relative time by a given factor.
521  *
522  * @param rel some duration
523  * @param factor integer to divide by
524  * @return FOREVER if rel=FOREVER or factor==0; otherwise rel/factor
525  */
526 struct GNUNET_TIME_Relative
527 GNUNET_TIME_relative_divide (struct GNUNET_TIME_Relative rel,
528                              unsigned long long factor)
529 {
530   struct GNUNET_TIME_Relative ret;
531
532   if ((0 == factor) ||
533       (rel.rel_value_us == GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us))
534     return GNUNET_TIME_UNIT_FOREVER_REL;
535   ret.rel_value_us = rel.rel_value_us / factor;
536   return ret;
537 }
538
539
540 /**
541  * Calculate the estimate time of arrival/completion
542  * for an operation.
543  *
544  * @param start when did the operation start?
545  * @param finished how much has been done?
546  * @param total how much must be done overall (same unit as for "finished")
547  * @return remaining duration for the operation,
548  *        assuming it continues at the same speed
549  */
550 struct GNUNET_TIME_Relative
551 GNUNET_TIME_calculate_eta (struct GNUNET_TIME_Absolute start,
552                            uint64_t finished,
553                            uint64_t total)
554 {
555   struct GNUNET_TIME_Relative dur;
556   double exp;
557   struct GNUNET_TIME_Relative ret;
558
559   GNUNET_break (finished <= total);
560   if (finished >= total)
561     return GNUNET_TIME_UNIT_ZERO;
562   if (0 == finished)
563     return GNUNET_TIME_UNIT_FOREVER_REL;
564   dur = GNUNET_TIME_absolute_get_duration (start);
565   exp = ((double) dur.rel_value_us) * ((double) total) / ((double) finished);
566   ret.rel_value_us = ((uint64_t) exp) - dur.rel_value_us;
567   return ret;
568 }
569
570
571 /**
572  * Add relative times together.
573  *
574  * @param a1 first timestamp
575  * @param a2 second timestamp
576  * @return FOREVER if either argument is FOREVER or on overflow; a1+a2 otherwise
577  */
578 struct GNUNET_TIME_Relative
579 GNUNET_TIME_relative_add (struct GNUNET_TIME_Relative a1,
580                           struct GNUNET_TIME_Relative a2)
581 {
582   struct GNUNET_TIME_Relative ret;
583
584   if ((a1.rel_value_us == UINT64_MAX) || (a2.rel_value_us == UINT64_MAX))
585     return GNUNET_TIME_UNIT_FOREVER_REL;
586   if (a1.rel_value_us + a2.rel_value_us < a1.rel_value_us)
587   {
588     GNUNET_break (0);
589     return GNUNET_TIME_UNIT_FOREVER_REL;
590   }
591   ret.rel_value_us = a1.rel_value_us + a2.rel_value_us;
592   return ret;
593 }
594
595
596 /**
597  * Subtract relative timestamp from the other.
598  *
599  * @param a1 first timestamp
600  * @param a2 second timestamp
601  * @return ZERO if a2>=a1 (including both FOREVER), FOREVER if a1 is FOREVER, a1-a2 otherwise
602  */
603 struct GNUNET_TIME_Relative
604 GNUNET_TIME_relative_subtract (struct GNUNET_TIME_Relative a1,
605                                struct GNUNET_TIME_Relative a2)
606 {
607   struct GNUNET_TIME_Relative ret;
608
609   if (a2.rel_value_us >= a1.rel_value_us)
610     return GNUNET_TIME_UNIT_ZERO;
611   if (a1.rel_value_us == UINT64_MAX)
612     return GNUNET_TIME_UNIT_FOREVER_REL;
613   ret.rel_value_us = a1.rel_value_us - a2.rel_value_us;
614   return ret;
615 }
616
617
618 /**
619  * Convert relative time to network byte order.
620  *
621  * @param a time to convert
622  * @return time in network byte order
623  */
624 struct GNUNET_TIME_RelativeNBO
625 GNUNET_TIME_relative_hton (struct GNUNET_TIME_Relative a)
626 {
627   struct GNUNET_TIME_RelativeNBO ret;
628
629   ret.rel_value_us__ = GNUNET_htonll (a.rel_value_us);
630   return ret;
631 }
632
633
634 /**
635  * Convert relative time from network byte order.
636  *
637  * @param a time to convert
638  * @return time in host byte order
639  */
640 struct GNUNET_TIME_Relative
641 GNUNET_TIME_relative_ntoh (struct GNUNET_TIME_RelativeNBO a)
642 {
643   struct GNUNET_TIME_Relative ret;
644
645   ret.rel_value_us = GNUNET_ntohll (a.rel_value_us__);
646   return ret;
647 }
648
649
650 /**
651  * Convert absolute time to network byte order.
652  *
653  * @param a time to convert
654  * @return time in network byte order
655  */
656 struct GNUNET_TIME_AbsoluteNBO
657 GNUNET_TIME_absolute_hton (struct GNUNET_TIME_Absolute a)
658 {
659   struct GNUNET_TIME_AbsoluteNBO ret;
660
661   ret.abs_value_us__ = GNUNET_htonll (a.abs_value_us);
662   return ret;
663 }
664
665
666 /**
667  * Convert absolute time from network byte order.
668  *
669  * @param a time to convert
670  * @return time in host byte order
671  */
672 struct GNUNET_TIME_Absolute
673 GNUNET_TIME_absolute_ntoh (struct GNUNET_TIME_AbsoluteNBO a)
674 {
675   struct GNUNET_TIME_Absolute ret;
676
677   ret.abs_value_us = GNUNET_ntohll (a.abs_value_us__);
678   return ret;
679 }
680
681
682 /**
683  * Return the current year (i.e. '2011').
684  */
685 unsigned int
686 GNUNET_TIME_get_current_year ()
687 {
688   time_t tp;
689   struct tm *t;
690
691   tp = time (NULL);
692   t = gmtime (&tp);
693   if (t == NULL)
694     return 0;
695   return t->tm_year + 1900;
696 }
697
698
699 /**
700  * Convert an expiration time to the respective year (rounds)
701  *
702  * @param at absolute time
703  * @return year a year (after 1970), 0 on error
704  */
705 unsigned int
706 GNUNET_TIME_time_to_year (struct GNUNET_TIME_Absolute at)
707 {
708   struct tm *t;
709   time_t tp;
710
711   tp = at.abs_value_us / 1000LL / 1000LL; /* microseconds to seconds */
712   t = gmtime (&tp);
713   if (t == NULL)
714     return 0;
715   return t->tm_year + 1900;
716 }
717
718
719 /**
720  * Convert a year to an expiration time of January 1st of that year.
721  *
722  * @param year a year (after 1970, please ;-)).
723  * @return absolute time for January 1st of that year.
724  */
725 struct GNUNET_TIME_Absolute
726 GNUNET_TIME_year_to_time (unsigned int year)
727 {
728   struct GNUNET_TIME_Absolute ret;
729   time_t tp;
730   struct tm t;
731
732   memset (&t, 0, sizeof(t));
733   if (year < 1900)
734   {
735     GNUNET_break (0);
736     return GNUNET_TIME_absolute_get ();  /* now */
737   }
738   t.tm_year = year - 1900;
739   t.tm_mday = 1;
740   t.tm_mon = 0;
741   t.tm_wday = 1;
742   t.tm_yday = 1;
743   tp = mktime (&t);
744   GNUNET_break (tp != (time_t) -1);
745   ret.abs_value_us = tp * 1000LL * 1000LL; /* seconds to microseconds */
746   return ret;
747 }
748
749
750 /**
751  * Randomized exponential back-off, starting at 1 ms
752  * and going up by a factor of 2+r, where 0 <= r <= 0.5, up
753  * to a maximum of the given threshold.
754  *
755  * @param r current backoff time, initially zero
756  * @param threshold maximum value for backoff
757  * @return the next backoff time
758  */
759 struct GNUNET_TIME_Relative
760 GNUNET_TIME_randomized_backoff (struct GNUNET_TIME_Relative rt,
761                                 struct GNUNET_TIME_Relative threshold)
762 {
763   double r = (rand () % 500) / 1000.0;
764   struct GNUNET_TIME_Relative t;
765
766   t = relative_multiply_double (
767     GNUNET_TIME_relative_max (GNUNET_TIME_UNIT_MILLISECONDS, rt),
768     2 + r);
769   return GNUNET_TIME_relative_min (threshold, t);
770 }
771
772
773 /**
774  * Return a random time value between 0.5*r and 1.5*r.
775  *
776  * @param r input time for scaling
777  * @return randomized time
778  */
779 struct GNUNET_TIME_Relative
780 GNUNET_TIME_randomize (struct GNUNET_TIME_Relative r)
781 {
782   double d = ((rand () % 1001) - 500) / 1000.0;
783
784   return relative_multiply_double (r, d);
785 }
786
787
788 /**
789  * Obtain the current time and make sure it is monotonically
790  * increasing.  Guards against systems without an RTC or
791  * clocks running backwards and other nasty surprises. Does
792  * not guarantee that the returned time is near the current
793  * time returned by #GNUNET_TIME_absolute_get().  Two
794  * subsequent calls (within a short time period) may return the
795  * same value. Persists the last returned time on disk to
796  * ensure that time never goes backwards. As a result, the
797  * resulting value can be used to check if a message is the
798  * "most recent" value and replays of older messages (from
799  * the same origin) would be discarded.
800  *
801  * @param cfg configuration, used to determine where to
802  *   store the time; user can also insist RTC is working
803  *   nicely and disable the feature
804  * @return monotonically increasing time
805  */
806 struct GNUNET_TIME_Absolute
807 GNUNET_TIME_absolute_get_monotonic (
808   const struct GNUNET_CONFIGURATION_Handle *cfg)
809 {
810   static const struct GNUNET_CONFIGURATION_Handle *last_cfg;
811   static struct GNUNET_TIME_Absolute last_time;
812   static struct GNUNET_DISK_MapHandle *map_handle;
813   static ATOMIC volatile uint64_t *map;
814   struct GNUNET_TIME_Absolute now;
815
816   now = GNUNET_TIME_absolute_get ();
817   if (last_cfg != cfg)
818   {
819     char *filename;
820
821     if (NULL != map_handle)
822     {
823       GNUNET_DISK_file_unmap (map_handle);
824       map_handle = NULL;
825     }
826     map = NULL;
827
828     last_cfg = cfg;
829     if ((NULL != cfg) &&
830         (GNUNET_OK ==
831          GNUNET_CONFIGURATION_get_value_filename (cfg,
832                                                   "util",
833                                                   "MONOTONIC_TIME_FILENAME",
834                                                   &filename)))
835     {
836       struct GNUNET_DISK_FileHandle *fh;
837
838       fh = GNUNET_DISK_file_open (filename,
839                                   GNUNET_DISK_OPEN_READWRITE
840                                   | GNUNET_DISK_OPEN_CREATE,
841                                   GNUNET_DISK_PERM_USER_WRITE
842                                   | GNUNET_DISK_PERM_GROUP_WRITE
843                                   | GNUNET_DISK_PERM_USER_READ
844                                   | GNUNET_DISK_PERM_GROUP_READ);
845       if (NULL == fh)
846       {
847         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
848                     _ ("Failed to map `%s', cannot assure monotonic time!\n"),
849                     filename);
850       }
851       else
852       {
853         off_t size;
854
855         size = 0;
856         GNUNET_break (GNUNET_OK == GNUNET_DISK_file_handle_size (fh, &size));
857         if (size < (off_t) sizeof(*map))
858         {
859           struct GNUNET_TIME_AbsoluteNBO o;
860
861           o = GNUNET_TIME_absolute_hton (now);
862           if (sizeof(o) != GNUNET_DISK_file_write (fh, &o, sizeof(o)))
863             size = 0;
864           else
865             size = sizeof(o);
866         }
867         if (size == sizeof(*map))
868         {
869           map = GNUNET_DISK_file_map (fh,
870                                       &map_handle,
871                                       GNUNET_DISK_MAP_TYPE_READWRITE,
872                                       sizeof(*map));
873           if (NULL == map)
874             GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
875                         _ (
876                           "Failed to map `%s', cannot assure monotonic time!\n"),
877                         filename);
878         }
879         else
880         {
881           GNUNET_log (
882             GNUNET_ERROR_TYPE_WARNING,
883             _ (
884               "Failed to setup monotonic time file `%s', cannot assure monotonic time!\n"),
885             filename);
886         }
887       }
888       GNUNET_DISK_file_close (fh);
889       GNUNET_free (filename);
890     }
891   }
892   if (NULL != map)
893   {
894     struct GNUNET_TIME_AbsoluteNBO mt;
895
896 #if __STDC_NO_ATOMICS__
897 #if __GNUC__
898     mt.abs_value_us__ = __sync_fetch_and_or (map, 0);
899 #else
900     mt.abs_value_us__ = *map;   /* godspeed, pray this is atomic */
901 #endif
902 #else
903     mt.abs_value_us__ = atomic_load (map);
904 #endif
905     last_time =
906       GNUNET_TIME_absolute_max (GNUNET_TIME_absolute_ntoh (mt), last_time);
907   }
908   if (now.abs_value_us <= last_time.abs_value_us)
909     now.abs_value_us = last_time.abs_value_us + 1;
910   last_time = now;
911   if (NULL != map)
912   {
913     uint64_t val = GNUNET_TIME_absolute_hton (now).abs_value_us__;
914 #if __STDC_NO_ATOMICS__
915 #if __GNUC__
916     (void) __sync_lock_test_and_set (map, val);
917 #else
918     *map = val;   /* godspeed, pray this is atomic */
919 #endif
920 #else
921     atomic_store (map, val);
922 #endif
923   }
924   return now;
925 }
926
927
928 /**
929  * Destructor
930  */
931 void __attribute__ ((destructor))
932 GNUNET_util_time_fini ()
933 {
934   (void) GNUNET_TIME_absolute_get_monotonic (NULL);
935 }
936
937
938 /* end of time.c */