1278307Srpaulo///////////////////////////////////////////////////////////////////////////////
2278307Srpaulo//
3278307Srpaulo/// \file       mytime.c
4278307Srpaulo/// \brief      Time handling functions
5278307Srpaulo//
6278307Srpaulo//  Author:     Lasse Collin
7278307Srpaulo//
8278307Srpaulo//  This file has been put into the public domain.
9278307Srpaulo//  You can do whatever you want with this file.
10278307Srpaulo//
11278307Srpaulo///////////////////////////////////////////////////////////////////////////////
12278307Srpaulo
13278307Srpaulo#include "private.h"
14278307Srpaulo
15278307Srpaulo#if !(defined(HAVE_CLOCK_GETTIME) && HAVE_DECL_CLOCK_MONOTONIC)
16278307Srpaulo#	include <sys/time.h>
17278307Srpaulo#endif
18278307Srpaulo
19278307Srpaulouint64_t opt_flush_timeout = 0;
20278307Srpaulo
21278307Srpaulostatic uint64_t start_time;
22278307Srpaulostatic uint64_t next_flush;
23278307Srpaulo
24278307Srpaulo
25278307Srpaulo/// \brief      Get the current time as milliseconds
26278307Srpaulo///
27278307Srpaulo/// It's relative to some point but not necessarily to the UNIX Epoch.
28278307Srpaulostatic uint64_t
29278307Srpaulomytime_now(void)
30278307Srpaulo{
31278307Srpaulo	// NOTE: HAVE_DECL_CLOCK_MONOTONIC is always defined to 0 or 1.
32278307Srpaulo#if defined(HAVE_CLOCK_GETTIME) && HAVE_DECL_CLOCK_MONOTONIC
33278307Srpaulo	// If CLOCK_MONOTONIC was available at compile time but for some
34278307Srpaulo	// reason isn't at runtime, fallback to CLOCK_REALTIME which
35278307Srpaulo	// according to POSIX is mandatory for all implementations.
36278307Srpaulo	static clockid_t clk_id = CLOCK_MONOTONIC;
37278307Srpaulo	struct timespec tv;
38278307Srpaulo	while (clock_gettime(clk_id, &tv))
39278307Srpaulo		clk_id = CLOCK_REALTIME;
40278307Srpaulo
41360523Sdelphij	return (uint64_t)tv.tv_sec * 1000 + (uint64_t)(tv.tv_nsec / 1000000);
42278307Srpaulo#else
43278307Srpaulo	struct timeval tv;
44278307Srpaulo	gettimeofday(&tv, NULL);
45360523Sdelphij	return (uint64_t)tv.tv_sec * 1000 + (uint64_t)(tv.tv_usec / 1000);
46278307Srpaulo#endif
47278307Srpaulo}
48278307Srpaulo
49278307Srpaulo
50278307Srpauloextern void
51278307Srpaulomytime_set_start_time(void)
52278307Srpaulo{
53278307Srpaulo	start_time = mytime_now();
54278307Srpaulo	return;
55278307Srpaulo}
56278307Srpaulo
57278307Srpaulo
58278307Srpauloextern uint64_t
59278307Srpaulomytime_get_elapsed(void)
60278307Srpaulo{
61278307Srpaulo	return mytime_now() - start_time;
62278307Srpaulo}
63278307Srpaulo
64278307Srpaulo
65278307Srpauloextern void
66278307Srpaulomytime_set_flush_time(void)
67278307Srpaulo{
68278307Srpaulo	next_flush = mytime_now() + opt_flush_timeout;
69278307Srpaulo	return;
70278307Srpaulo}
71278307Srpaulo
72278307Srpaulo
73278307Srpauloextern int
74278307Srpaulomytime_get_flush_timeout(void)
75278307Srpaulo{
76278307Srpaulo	if (opt_flush_timeout == 0 || opt_mode != MODE_COMPRESS)
77278307Srpaulo		return -1;
78278307Srpaulo
79278307Srpaulo	const uint64_t now = mytime_now();
80278307Srpaulo	if (now >= next_flush)
81278307Srpaulo		return 0;
82278307Srpaulo
83278307Srpaulo	const uint64_t remaining = next_flush - now;
84278307Srpaulo	return remaining > INT_MAX ? INT_MAX : (int)remaining;
85278307Srpaulo}
86