aboutsummaryrefslogtreecommitdiff
path: root/src/util/time.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/time.c')
-rw-r--r--src/util/time.c990
1 files changed, 0 insertions, 990 deletions
diff --git a/src/util/time.c b/src/util/time.c
deleted file mode 100644
index cf072aebf..000000000
--- a/src/util/time.c
+++ /dev/null
@@ -1,990 +0,0 @@
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 */
45static long long timestamp_offset;
46
47void
48GNUNET_TIME_set_offset (long long offset)
49{
50 timestamp_offset = offset;
51}
52
53
54long long
55GNUNET_TIME_get_offset ()
56{
57 return timestamp_offset;
58}
59
60
61bool
62GNUNET_TIME_absolute_approx_eq (struct GNUNET_TIME_Absolute a1,
63 struct GNUNET_TIME_Absolute a2,
64 struct GNUNET_TIME_Relative t)
65{
66 struct GNUNET_TIME_Relative delta;
67
68 delta = GNUNET_TIME_relative_min (
69 GNUNET_TIME_absolute_get_difference (a1, a2),
70 GNUNET_TIME_absolute_get_difference (a2, a1));
71 return GNUNET_TIME_relative_cmp (delta,
72 <=,
73 t);
74}
75
76
77struct GNUNET_TIME_Timestamp
78GNUNET_TIME_absolute_to_timestamp (struct GNUNET_TIME_Absolute at)
79{
80 struct GNUNET_TIME_Timestamp ts;
81
82 if (GNUNET_TIME_absolute_is_never (at))
83 return GNUNET_TIME_UNIT_FOREVER_TS;
84 ts.abs_time.abs_value_us = at.abs_value_us - at.abs_value_us % 1000000;
85 return ts;
86}
87
88
89struct GNUNET_TIME_TimestampNBO
90GNUNET_TIME_timestamp_hton (struct GNUNET_TIME_Timestamp t)
91{
92 struct GNUNET_TIME_TimestampNBO tn;
93
94 tn.abs_time_nbo = GNUNET_TIME_absolute_hton (t.abs_time);
95 return tn;
96}
97
98
99struct GNUNET_TIME_Timestamp
100GNUNET_TIME_timestamp_ntoh (struct GNUNET_TIME_TimestampNBO tn)
101{
102 struct GNUNET_TIME_Timestamp t;
103
104 t.abs_time = GNUNET_TIME_absolute_ntoh (tn.abs_time_nbo);
105 return t;
106}
107
108
109struct GNUNET_TIME_Absolute
110GNUNET_TIME_absolute_get ()
111{
112 struct GNUNET_TIME_Absolute ret;
113 struct timeval tv;
114
115 gettimeofday (&tv, NULL);
116 ret.abs_value_us = (uint64_t) (((uint64_t) tv.tv_sec * 1000LL * 1000LL)
117 + ((uint64_t) tv.tv_usec))
118 + timestamp_offset;
119 return ret;
120}
121
122
123struct GNUNET_TIME_Timestamp
124GNUNET_TIME_timestamp_get ()
125{
126 return GNUNET_TIME_absolute_to_timestamp (
127 GNUNET_TIME_absolute_get ());
128}
129
130
131struct GNUNET_TIME_Relative
132GNUNET_TIME_relative_get_zero_ ()
133{
134 static struct GNUNET_TIME_Relative zero;
135
136 return zero;
137}
138
139
140struct GNUNET_TIME_Absolute
141GNUNET_TIME_absolute_get_zero_ ()
142{
143 static struct GNUNET_TIME_Absolute zero;
144
145 return zero;
146}
147
148
149struct GNUNET_TIME_Relative
150GNUNET_TIME_relative_get_unit_ ()
151{
152 static struct GNUNET_TIME_Relative one = { 1 };
153
154 return one;
155}
156
157
158struct GNUNET_TIME_Relative
159GNUNET_TIME_relative_get_millisecond_ ()
160{
161 static struct GNUNET_TIME_Relative one = { 1000 };
162
163 return one;
164}
165
166
167struct GNUNET_TIME_Relative
168GNUNET_TIME_relative_get_second_ ()
169{
170 static struct GNUNET_TIME_Relative one = { 1000 * 1000LL };
171
172 return one;
173}
174
175
176struct GNUNET_TIME_Relative
177GNUNET_TIME_relative_get_minute_ ()
178{
179 static struct GNUNET_TIME_Relative one = { 60 * 1000 * 1000LL };
180
181 return one;
182}
183
184
185struct GNUNET_TIME_Relative
186GNUNET_TIME_relative_get_hour_ ()
187{
188 static struct GNUNET_TIME_Relative one = { 60 * 60 * 1000 * 1000LL };
189
190 return one;
191}
192
193
194struct GNUNET_TIME_Relative
195GNUNET_TIME_relative_get_forever_ ()
196{
197 static struct GNUNET_TIME_Relative forever = { UINT64_MAX };
198
199 return forever;
200}
201
202
203struct GNUNET_TIME_Absolute
204GNUNET_TIME_absolute_get_forever_ ()
205{
206 static struct GNUNET_TIME_Absolute forever = { UINT64_MAX };
207
208 return forever;
209}
210
211
212const char *
213GNUNET_TIME_timestamp2s (struct GNUNET_TIME_Timestamp ts)
214{
215 static GNUNET_THREAD_LOCAL char buf[255];
216 time_t tt;
217 struct tm *tp;
218
219 if (GNUNET_TIME_absolute_is_never (ts.abs_time))
220 return "end of time";
221 tt = ts.abs_time.abs_value_us / 1000LL / 1000LL;
222 tp = localtime (&tt);
223 /* This is hacky, but i don't know a way to detect libc character encoding.
224 * Just expect utf8 from glibc these days.
225 * As for msvcrt, use the wide variant, which always returns utf16
226 * (otherwise we'd have to detect current codepage or use W32API character
227 * set conversion routines to convert to UTF8).
228 */
229 strftime (buf,
230 sizeof(buf),
231 "%a %b %d %H:%M:%S %Y",
232 tp);
233 return buf;
234}
235
236
237const char *
238GNUNET_TIME_absolute2s (struct GNUNET_TIME_Absolute t)
239{
240 static GNUNET_THREAD_LOCAL char buf[255];
241 time_t tt;
242 struct tm *tp;
243
244 if (GNUNET_TIME_absolute_is_never (t))
245 return "end of time";
246 tt = t.abs_value_us / 1000LL / 1000LL;
247 tp = localtime (&tt);
248 /* This is hacky, but i don't know a way to detect libc character encoding.
249 * Just expect utf8 from glibc these days.
250 * As for msvcrt, use the wide variant, which always returns utf16
251 * (otherwise we'd have to detect current codepage or use W32API character
252 * set conversion routines to convert to UTF8).
253 */
254 strftime (buf,
255 sizeof(buf),
256 "%a %b %d %H:%M:%S %Y",
257 tp);
258 return buf;
259}
260
261
262const char *
263GNUNET_TIME_relative2s (struct GNUNET_TIME_Relative delta,
264 bool do_round)
265{
266 static GNUNET_THREAD_LOCAL char buf[128];
267 const char *unit = /* time unit */ "µs";
268 uint64_t dval = delta.rel_value_us;
269
270 if (GNUNET_TIME_relative_is_forever (delta))
271 return "forever";
272 if (0 == delta.rel_value_us)
273 return "0 ms";
274 if ( ((GNUNET_YES == do_round) &&
275 (dval > 5 * 1000)) ||
276 (0 == (dval % 1000)))
277 {
278 dval = dval / 1000;
279 unit = /* time unit */ "ms";
280 if (((GNUNET_YES == do_round) && (dval > 5 * 1000)) || (0 == (dval % 1000)))
281 {
282 dval = dval / 1000;
283 unit = /* time unit */ "s";
284 if (((GNUNET_YES == do_round) && (dval > 5 * 60)) || (0 == (dval % 60)))
285 {
286 dval = dval / 60;
287 unit = /* time unit */ "m";
288 if (((GNUNET_YES == do_round) && (dval > 5 * 60)) || (0 == (dval % 60)))
289 {
290 dval = dval / 60;
291 unit = /* time unit */ "h";
292 if (((GNUNET_YES == do_round) && (dval > 5 * 24)) ||
293 (0 == (dval % 24)))
294 {
295 dval = dval / 24;
296 if (1 == dval)
297 unit = /* time unit */ "day";
298 else
299 unit = /* time unit */ "days";
300 }
301 }
302 }
303 }
304 }
305 GNUNET_snprintf (buf,
306 sizeof(buf),
307 "%llu %s",
308 (unsigned long long) dval,
309 unit);
310 return buf;
311}
312
313
314struct GNUNET_TIME_Absolute
315GNUNET_TIME_relative_to_absolute (struct GNUNET_TIME_Relative rel)
316{
317 struct GNUNET_TIME_Absolute ret;
318
319 if (GNUNET_TIME_relative_is_forever (rel))
320 return GNUNET_TIME_UNIT_FOREVER_ABS;
321 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
322
323 if (rel.rel_value_us + now.abs_value_us < rel.rel_value_us)
324 {
325 GNUNET_break (0); /* overflow... */
326 return GNUNET_TIME_UNIT_FOREVER_ABS;
327 }
328 ret.abs_value_us = rel.rel_value_us + now.abs_value_us;
329 return ret;
330}
331
332
333struct GNUNET_TIME_Timestamp
334GNUNET_TIME_relative_to_timestamp (struct GNUNET_TIME_Relative rel)
335{
336 return GNUNET_TIME_absolute_to_timestamp (
337 GNUNET_TIME_relative_to_absolute (rel));
338}
339
340
341struct GNUNET_TIME_Relative
342GNUNET_TIME_relative_min (struct GNUNET_TIME_Relative t1,
343 struct GNUNET_TIME_Relative t2)
344{
345 return (t1.rel_value_us < t2.rel_value_us) ? t1 : t2;
346}
347
348
349struct GNUNET_TIME_Relative
350GNUNET_TIME_relative_max (struct GNUNET_TIME_Relative t1,
351 struct GNUNET_TIME_Relative t2)
352{
353 return (t1.rel_value_us > t2.rel_value_us) ? t1 : t2;
354}
355
356
357struct GNUNET_TIME_Absolute
358GNUNET_TIME_absolute_min (struct GNUNET_TIME_Absolute t1,
359 struct GNUNET_TIME_Absolute t2)
360{
361 return (t1.abs_value_us < t2.abs_value_us) ? t1 : t2;
362}
363
364
365struct GNUNET_TIME_Absolute
366GNUNET_TIME_absolute_max (struct GNUNET_TIME_Absolute t1,
367 struct GNUNET_TIME_Absolute t2)
368{
369 return (t1.abs_value_us > t2.abs_value_us) ? t1 : t2;
370}
371
372
373struct GNUNET_TIME_Timestamp
374GNUNET_TIME_timestamp_max (struct GNUNET_TIME_Timestamp t1,
375 struct GNUNET_TIME_Timestamp t2)
376{
377 return (t1.abs_time.abs_value_us > t2.abs_time.abs_value_us) ? t1 : t2;
378}
379
380
381struct GNUNET_TIME_Timestamp
382GNUNET_TIME_timestamp_min (struct GNUNET_TIME_Timestamp t1,
383 struct GNUNET_TIME_Timestamp t2)
384{
385 return (t1.abs_time.abs_value_us < t2.abs_time.abs_value_us) ? t1 : t2;
386}
387
388
389struct GNUNET_TIME_Absolute
390GNUNET_TIME_absolute_round_down (struct GNUNET_TIME_Absolute at,
391 struct GNUNET_TIME_Relative rt)
392{
393 struct GNUNET_TIME_Absolute ret;
394
395 GNUNET_assert (! GNUNET_TIME_relative_is_zero (rt));
396 ret.abs_value_us
397 = at.abs_value_us
398 - at.abs_value_us % rt.rel_value_us;
399 return ret;
400}
401
402
403struct GNUNET_TIME_Relative
404GNUNET_TIME_absolute_get_remaining (struct GNUNET_TIME_Absolute future)
405{
406 struct GNUNET_TIME_Relative ret;
407
408 if (GNUNET_TIME_absolute_is_never (future))
409 return GNUNET_TIME_UNIT_FOREVER_REL;
410 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
411
412 if (now.abs_value_us > future.abs_value_us)
413 return GNUNET_TIME_UNIT_ZERO;
414 ret.rel_value_us = future.abs_value_us - now.abs_value_us;
415 return ret;
416}
417
418
419struct GNUNET_TIME_Relative
420GNUNET_TIME_absolute_get_difference (struct GNUNET_TIME_Absolute start,
421 struct GNUNET_TIME_Absolute end)
422{
423 struct GNUNET_TIME_Relative ret;
424
425 if (GNUNET_TIME_absolute_is_never (end))
426 return GNUNET_TIME_UNIT_FOREVER_REL;
427 if (end.abs_value_us < start.abs_value_us)
428 return GNUNET_TIME_UNIT_ZERO;
429 ret.rel_value_us = end.abs_value_us - start.abs_value_us;
430 return ret;
431}
432
433
434struct GNUNET_TIME_Relative
435GNUNET_TIME_absolute_get_duration (struct GNUNET_TIME_Absolute whence)
436{
437 struct GNUNET_TIME_Absolute now;
438 struct GNUNET_TIME_Relative ret;
439
440 now = GNUNET_TIME_absolute_get ();
441 if (whence.abs_value_us > now.abs_value_us)
442 return GNUNET_TIME_UNIT_ZERO;
443 ret.rel_value_us = now.abs_value_us - whence.abs_value_us;
444 return ret;
445}
446
447
448struct GNUNET_TIME_Absolute
449GNUNET_TIME_absolute_add (struct GNUNET_TIME_Absolute start,
450 struct GNUNET_TIME_Relative duration)
451{
452 struct GNUNET_TIME_Absolute ret;
453
454 if (GNUNET_TIME_absolute_is_never (start) ||
455 GNUNET_TIME_relative_is_forever (duration))
456 return GNUNET_TIME_UNIT_FOREVER_ABS;
457 if (start.abs_value_us + duration.rel_value_us < start.abs_value_us)
458 {
459 GNUNET_break (0);
460 return GNUNET_TIME_UNIT_FOREVER_ABS;
461 }
462 ret.abs_value_us = start.abs_value_us + duration.rel_value_us;
463 return ret;
464}
465
466
467struct GNUNET_TIME_Absolute
468GNUNET_TIME_absolute_subtract (struct GNUNET_TIME_Absolute start,
469 struct GNUNET_TIME_Relative duration)
470{
471 struct GNUNET_TIME_Absolute ret;
472
473 if (start.abs_value_us <= duration.rel_value_us)
474 return GNUNET_TIME_UNIT_ZERO_ABS;
475 if (GNUNET_TIME_absolute_is_never (start))
476 return GNUNET_TIME_UNIT_FOREVER_ABS;
477 ret.abs_value_us = start.abs_value_us - duration.rel_value_us;
478 return ret;
479}
480
481
482struct GNUNET_TIME_Relative
483GNUNET_TIME_relative_multiply (struct GNUNET_TIME_Relative rel,
484 unsigned long long factor)
485{
486 struct GNUNET_TIME_Relative ret;
487
488 if (0 == factor)
489 return GNUNET_TIME_UNIT_ZERO;
490 if (GNUNET_TIME_relative_is_forever (rel))
491 return GNUNET_TIME_UNIT_FOREVER_REL;
492 ret.rel_value_us = rel.rel_value_us * factor;
493 if (ret.rel_value_us / factor != rel.rel_value_us)
494 {
495 GNUNET_break (0);
496 return GNUNET_TIME_UNIT_FOREVER_REL;
497 }
498 return ret;
499}
500
501
502struct GNUNET_TIME_Relative
503relative_multiply_double (struct GNUNET_TIME_Relative rel,
504 double factor)
505{
506 struct GNUNET_TIME_Relative out;
507 double m;
508
509 GNUNET_assert (0 <= factor);
510
511 if (0 == factor)
512 return GNUNET_TIME_UNIT_ZERO;
513 if (GNUNET_TIME_relative_is_forever (rel))
514 return GNUNET_TIME_UNIT_FOREVER_REL;
515
516 m = ((double) rel.rel_value_us) * factor;
517
518 if (m >= (double) (GNUNET_TIME_UNIT_FOREVER_REL).rel_value_us)
519 {
520 GNUNET_break (0);
521 return GNUNET_TIME_UNIT_FOREVER_REL;
522 }
523
524 out.rel_value_us = (uint64_t) m;
525 return out;
526}
527
528
529struct GNUNET_TIME_Relative
530GNUNET_TIME_relative_saturating_multiply (struct GNUNET_TIME_Relative rel,
531 unsigned long long factor)
532{
533 struct GNUNET_TIME_Relative ret;
534
535 if (0 == factor)
536 return GNUNET_TIME_UNIT_ZERO;
537 if (GNUNET_TIME_relative_is_forever (rel))
538 return GNUNET_TIME_UNIT_FOREVER_REL;
539 ret.rel_value_us = rel.rel_value_us * factor;
540 if (ret.rel_value_us / factor != rel.rel_value_us)
541 {
542 return GNUNET_TIME_UNIT_FOREVER_REL;
543 }
544 return ret;
545}
546
547
548struct GNUNET_TIME_Relative
549GNUNET_TIME_relative_divide (struct GNUNET_TIME_Relative rel,
550 unsigned long long factor)
551{
552 struct GNUNET_TIME_Relative ret;
553
554 if ((0 == factor) ||
555 (GNUNET_TIME_relative_is_forever (rel)))
556 return GNUNET_TIME_UNIT_FOREVER_REL;
557 ret.rel_value_us = rel.rel_value_us / factor;
558 return ret;
559}
560
561
562struct GNUNET_TIME_Relative
563GNUNET_TIME_calculate_eta (struct GNUNET_TIME_Absolute start,
564 uint64_t finished,
565 uint64_t total)
566{
567 struct GNUNET_TIME_Relative due;
568 double exp;
569 struct GNUNET_TIME_Relative ret;
570
571 GNUNET_break (finished <= total);
572 if (finished >= total)
573 return GNUNET_TIME_UNIT_ZERO;
574 if (0 == finished)
575 return GNUNET_TIME_UNIT_FOREVER_REL;
576 due = GNUNET_TIME_absolute_get_duration (start);
577 exp = ((double) due.rel_value_us) * ((double) total) / ((double) finished);
578 ret.rel_value_us = ((uint64_t) exp) - due.rel_value_us;
579 return ret;
580}
581
582
583struct GNUNET_TIME_Relative
584GNUNET_TIME_relative_add (struct GNUNET_TIME_Relative a1,
585 struct GNUNET_TIME_Relative a2)
586{
587 struct GNUNET_TIME_Relative ret;
588
589 if ((a1.rel_value_us == UINT64_MAX) || (a2.rel_value_us == UINT64_MAX))
590 return GNUNET_TIME_UNIT_FOREVER_REL;
591 if (a1.rel_value_us + a2.rel_value_us < a1.rel_value_us)
592 {
593 GNUNET_break (0);
594 return GNUNET_TIME_UNIT_FOREVER_REL;
595 }
596 ret.rel_value_us = a1.rel_value_us + a2.rel_value_us;
597 return ret;
598}
599
600
601struct GNUNET_TIME_Relative
602GNUNET_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
616struct GNUNET_TIME_RelativeNBO
617GNUNET_TIME_relative_hton (struct GNUNET_TIME_Relative a)
618{
619 struct GNUNET_TIME_RelativeNBO ret;
620
621 ret.rel_value_us__ = GNUNET_htonll (a.rel_value_us);
622 return ret;
623}
624
625
626struct GNUNET_TIME_Relative
627GNUNET_TIME_relative_ntoh (struct GNUNET_TIME_RelativeNBO a)
628{
629 struct GNUNET_TIME_Relative ret;
630
631 ret.rel_value_us = GNUNET_ntohll (a.rel_value_us__);
632 return ret;
633}
634
635
636struct GNUNET_TIME_AbsoluteNBO
637GNUNET_TIME_absolute_hton (struct GNUNET_TIME_Absolute a)
638{
639 struct GNUNET_TIME_AbsoluteNBO ret;
640
641 ret.abs_value_us__ = GNUNET_htonll (a.abs_value_us);
642 return ret;
643}
644
645
646bool
647GNUNET_TIME_absolute_is_never (struct GNUNET_TIME_Absolute abs)
648{
649 return GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us == abs.abs_value_us;
650}
651
652
653bool
654GNUNET_TIME_relative_is_forever (struct GNUNET_TIME_Relative rel)
655{
656 return GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us == rel.rel_value_us;
657}
658
659
660bool
661GNUNET_TIME_relative_is_zero (struct GNUNET_TIME_Relative rel)
662{
663 return 0 == rel.rel_value_us;
664}
665
666
667bool
668GNUNET_TIME_absolute_is_past (struct GNUNET_TIME_Absolute abs)
669{
670 struct GNUNET_TIME_Absolute now;
671
672 now = GNUNET_TIME_absolute_get ();
673 return abs.abs_value_us < now.abs_value_us;
674}
675
676
677bool
678GNUNET_TIME_absolute_is_future (struct GNUNET_TIME_Absolute abs)
679{
680 struct GNUNET_TIME_Absolute now;
681
682 now = GNUNET_TIME_absolute_get ();
683 return abs.abs_value_us > now.abs_value_us;
684}
685
686
687struct GNUNET_TIME_Absolute
688GNUNET_TIME_absolute_from_ms (uint64_t ms_after_epoch)
689{
690 struct GNUNET_TIME_Absolute ret;
691
692 ret.abs_value_us = GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us
693 * ms_after_epoch;
694 if (ret.abs_value_us / GNUNET_TIME_UNIT_MILLISECONDS.rel_value_us !=
695 ms_after_epoch)
696 ret = GNUNET_TIME_UNIT_FOREVER_ABS;
697 return ret;
698}
699
700
701struct GNUNET_TIME_Absolute
702GNUNET_TIME_absolute_from_s (uint64_t s_after_epoch)
703{
704 struct GNUNET_TIME_Absolute ret;
705
706 ret.abs_value_us = GNUNET_TIME_UNIT_SECONDS.rel_value_us * s_after_epoch;
707 if (ret.abs_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us !=
708 s_after_epoch)
709 ret = GNUNET_TIME_UNIT_FOREVER_ABS;
710 return ret;
711}
712
713
714struct GNUNET_TIME_Timestamp
715GNUNET_TIME_timestamp_from_s (uint64_t s_after_epoch)
716{
717 struct GNUNET_TIME_Timestamp ret;
718
719 ret.abs_time.abs_value_us
720 = GNUNET_TIME_UNIT_SECONDS.rel_value_us * s_after_epoch;
721 if (ret.abs_time.abs_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us
722 != s_after_epoch)
723 ret = GNUNET_TIME_UNIT_FOREVER_TS;
724 return ret;
725}
726
727
728uint64_t
729GNUNET_TIME_timestamp_to_s (struct GNUNET_TIME_Timestamp ts)
730{
731 return ts.abs_time.abs_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us;
732}
733
734
735struct GNUNET_TIME_Absolute
736GNUNET_TIME_absolute_ntoh (struct GNUNET_TIME_AbsoluteNBO a)
737{
738 struct GNUNET_TIME_Absolute ret;
739
740 ret.abs_value_us = GNUNET_ntohll (a.abs_value_us__);
741 return ret;
742}
743
744
745unsigned int
746GNUNET_TIME_get_current_year ()
747{
748 time_t tp;
749 struct tm *t;
750
751 tp = time (NULL);
752 t = gmtime (&tp);
753 if (t == NULL)
754 return 0;
755 return t->tm_year + 1900;
756}
757
758
759unsigned int
760GNUNET_TIME_time_to_year (struct GNUNET_TIME_Absolute at)
761{
762 struct tm *t;
763 time_t tp;
764
765 tp = at.abs_value_us / 1000LL / 1000LL; /* microseconds to seconds */
766 t = gmtime (&tp);
767 if (t == NULL)
768 return 0;
769 return t->tm_year + 1900;
770}
771
772
773#ifndef HAVE_TIMEGM
774/**
775 * As suggested in the timegm() man page.
776 */
777static time_t
778my_timegm (struct tm *tm)
779{
780 time_t ret;
781 char *tz;
782
783 tz = getenv ("TZ");
784 setenv ("TZ", "", 1);
785 tzset ();
786 ret = mktime (tm);
787 if (tz)
788 setenv ("TZ", tz, 1);
789 else
790 unsetenv ("TZ");
791 tzset ();
792 return ret;
793}
794
795
796#endif
797
798
799struct GNUNET_TIME_Absolute
800GNUNET_TIME_year_to_time (unsigned int year)
801{
802 struct GNUNET_TIME_Absolute ret;
803 time_t tp;
804 struct tm t;
805
806 memset (&t, 0, sizeof(t));
807 if (year < 1900)
808 {
809 GNUNET_break (0);
810 return GNUNET_TIME_absolute_get (); /* now */
811 }
812 t.tm_year = year - 1900;
813 t.tm_mday = 1;
814 t.tm_mon = 0;
815 t.tm_wday = 1;
816 t.tm_yday = 1;
817#ifndef HAVE_TIMEGM
818 tp = my_timegm (&t);
819#else
820 tp = timegm (&t);
821#endif
822 GNUNET_break (tp != (time_t) -1);
823 ret.abs_value_us = tp * 1000LL * 1000LL; /* seconds to microseconds */
824 return ret;
825}
826
827
828struct GNUNET_TIME_Relative
829GNUNET_TIME_randomized_backoff (struct GNUNET_TIME_Relative rt,
830 struct GNUNET_TIME_Relative threshold)
831{
832 double r = (rand () % 500) / 1000.0;
833 struct GNUNET_TIME_Relative t;
834
835 t = relative_multiply_double (
836 GNUNET_TIME_relative_max (GNUNET_TIME_UNIT_MILLISECONDS, rt),
837 2 + r);
838 return GNUNET_TIME_relative_min (threshold, t);
839}
840
841
842bool
843GNUNET_TIME_absolute_is_zero (struct GNUNET_TIME_Absolute abs)
844{
845 return 0 == abs.abs_value_us;
846}
847
848
849struct GNUNET_TIME_Relative
850GNUNET_TIME_randomize (struct GNUNET_TIME_Relative r)
851{
852 double d = ((rand () % 1001) + 500) / 1000.0;
853
854 return relative_multiply_double (r, d);
855}
856
857
858struct GNUNET_TIME_Absolute
859GNUNET_TIME_absolute_get_monotonic (
860 const struct GNUNET_CONFIGURATION_Handle *cfg)
861{
862 static const struct GNUNET_CONFIGURATION_Handle *last_cfg;
863 static struct GNUNET_TIME_Absolute last_time;
864 static struct GNUNET_DISK_MapHandle *map_handle;
865 static ATOMIC volatile uint64_t *map;
866 struct GNUNET_TIME_Absolute now;
867
868 now = GNUNET_TIME_absolute_get ();
869 if (last_cfg != cfg)
870 {
871 char *filename;
872
873 if (NULL != map_handle)
874 {
875 GNUNET_DISK_file_unmap (map_handle);
876 map_handle = NULL;
877 }
878 map = NULL;
879
880 last_cfg = cfg;
881 if ((NULL != cfg) &&
882 (GNUNET_OK ==
883 GNUNET_CONFIGURATION_get_value_filename (cfg,
884 "util",
885 "MONOTONIC_TIME_FILENAME",
886 &filename)))
887 {
888 struct GNUNET_DISK_FileHandle *fh;
889
890 fh = GNUNET_DISK_file_open (filename,
891 GNUNET_DISK_OPEN_READWRITE
892 | GNUNET_DISK_OPEN_CREATE,
893 GNUNET_DISK_PERM_USER_WRITE
894 | GNUNET_DISK_PERM_GROUP_WRITE
895 | GNUNET_DISK_PERM_USER_READ
896 | GNUNET_DISK_PERM_GROUP_READ);
897 if (NULL == fh)
898 {
899 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
900 _ ("Failed to map `%s', cannot assure monotonic time!\n"),
901 filename);
902 }
903 else
904 {
905 off_t size;
906
907 size = 0;
908 GNUNET_break (GNUNET_OK == GNUNET_DISK_file_handle_size (fh, &size));
909 if (size < (off_t) sizeof(*map))
910 {
911 struct GNUNET_TIME_AbsoluteNBO o;
912
913 o = GNUNET_TIME_absolute_hton (now);
914 if (sizeof(o) != GNUNET_DISK_file_write (fh, &o, sizeof(o)))
915 size = 0;
916 else
917 size = sizeof(o);
918 }
919 if (size == sizeof(*map))
920 {
921 map = GNUNET_DISK_file_map (fh,
922 &map_handle,
923 GNUNET_DISK_MAP_TYPE_READWRITE,
924 sizeof(*map));
925 if (NULL == map)
926 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
927 _ (
928 "Failed to map `%s', cannot assure monotonic time!\n"),
929 filename);
930 }
931 else
932 {
933 GNUNET_log (
934 GNUNET_ERROR_TYPE_WARNING,
935 _ (
936 "Failed to setup monotonic time file `%s', cannot assure monotonic time!\n"),
937 filename);
938 }
939 }
940 GNUNET_DISK_file_close (fh);
941 GNUNET_free (filename);
942 }
943 }
944 if (NULL != map)
945 {
946 struct GNUNET_TIME_AbsoluteNBO mt;
947
948#if __STDC_NO_ATOMICS__
949#if __GNUC__
950 mt.abs_value_us__ = __sync_fetch_and_or (map, 0);
951#else
952 mt.abs_value_us__ = *map; /* godspeed, pray this is atomic */
953#endif
954#else
955 mt.abs_value_us__ = atomic_load (map);
956#endif
957 last_time =
958 GNUNET_TIME_absolute_max (GNUNET_TIME_absolute_ntoh (mt), last_time);
959 }
960 if (now.abs_value_us <= last_time.abs_value_us)
961 now.abs_value_us = last_time.abs_value_us + 1;
962 last_time = now;
963 if (NULL != map)
964 {
965 uint64_t val = GNUNET_TIME_absolute_hton (now).abs_value_us__;
966#if __STDC_NO_ATOMICS__
967#if __GNUC__
968 (void) __sync_lock_test_and_set (map, val);
969#else
970 *map = val; /* godspeed, pray this is atomic */
971#endif
972#else
973 atomic_store (map, val);
974#endif
975 }
976 return now;
977}
978
979
980/**
981 * Destructor
982 */
983void __attribute__ ((destructor))
984GNUNET_util_time_fini ()
985{
986 (void) GNUNET_TIME_absolute_get_monotonic (NULL);
987}
988
989
990/* end of time.c */