File Coverage

amqp_time.c
Criterion Covered Total %
statement 36 87 41.3
branch 16 52 30.7
condition n/a
subroutine n/a
pod n/a
total 52 139 37.4


line stmt bran cond sub pod time code
1             // Copyright 2007 - 2021, Alan Antonuk and the rabbitmq-c contributors.
2             // SPDX-License-Identifier: mit
3              
4             #include "amqp_time.h"
5             #include "rabbitmq-c/amqp.h"
6             #include
7             #include
8             #include
9              
10             #if (defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || \
11             defined(__MINGW32__) || defined(__MINGW64__))
12             #define AMQP_WIN_TIMER_API
13             #elif (defined(machintosh) || defined(__APPLE__) || defined(__APPLE_CC__))
14             #define AMQP_MAC_TIMER_API
15             #else
16             #define AMQP_POSIX_TIMER_API
17             #endif
18              
19             #ifdef AMQP_WIN_TIMER_API
20             #ifndef WIN32_LEAN_AND_MEAN
21             #define WIN32_LEAN_AND_MEAN
22             #endif
23             #include
24              
25             uint64_t amqp_get_monotonic_timestamp(void) {
26             static double NS_PER_COUNT = 0;
27             LARGE_INTEGER perf_count;
28              
29             if (0 == NS_PER_COUNT) {
30             LARGE_INTEGER perf_frequency;
31             if (!QueryPerformanceFrequency(&perf_frequency)) {
32             return 0;
33             }
34             NS_PER_COUNT = (double)AMQP_NS_PER_S / perf_frequency.QuadPart;
35             }
36              
37             if (!QueryPerformanceCounter(&perf_count)) {
38             return 0;
39             }
40              
41             return (uint64_t)(perf_count.QuadPart * NS_PER_COUNT);
42             }
43             #endif /* AMQP_WIN_TIMER_API */
44              
45             #ifdef AMQP_MAC_TIMER_API
46             #include
47              
48             uint64_t amqp_get_monotonic_timestamp(void) {
49             static mach_timebase_info_data_t s_timebase = {0, 0};
50             uint64_t timestamp;
51              
52             timestamp = mach_absolute_time();
53              
54             if (s_timebase.denom == 0) {
55             mach_timebase_info(&s_timebase);
56             if (0 == s_timebase.denom) {
57             return 0;
58             }
59             }
60              
61             timestamp *= (uint64_t)s_timebase.numer;
62             timestamp /= (uint64_t)s_timebase.denom;
63              
64             return timestamp;
65             }
66             #endif /* AMQP_MAC_TIMER_API */
67              
68             #ifdef AMQP_POSIX_TIMER_API
69             #include
70              
71 2           uint64_t amqp_get_monotonic_timestamp(void) {
72             #ifdef __hpux
73             return (uint64_t)gethrtime();
74             #else
75             struct timespec tp;
76 2 50         if (-1 == clock_gettime(CLOCK_MONOTONIC, &tp)) {
77 0           return 0;
78             }
79              
80 2           return ((uint64_t)tp.tv_sec * AMQP_NS_PER_S + (uint64_t)tp.tv_nsec);
81             #endif
82             }
83             #endif /* AMQP_POSIX_TIMER_API */
84              
85 2           int amqp_time_from_now(amqp_time_t *time, const struct timeval *timeout) {
86             uint64_t now_ns;
87             uint64_t delta_ns;
88              
89 2 50         assert(NULL != time);
90              
91 2 100         if (NULL == timeout) {
92 1           *time = amqp_time_infinite();
93 1           return AMQP_STATUS_OK;
94             }
95              
96 1 50         if (timeout->tv_sec < 0 || timeout->tv_usec < 0) {
    50          
97 0           return AMQP_STATUS_INVALID_PARAMETER;
98             }
99              
100 1           delta_ns = (uint64_t)timeout->tv_sec * AMQP_NS_PER_S +
101 1           (uint64_t)timeout->tv_usec * AMQP_NS_PER_US;
102              
103 1           now_ns = amqp_get_monotonic_timestamp();
104 1 50         if (0 == now_ns) {
105 0           return AMQP_STATUS_TIMER_FAILURE;
106             }
107              
108 1           time->time_point_ns = now_ns + delta_ns;
109 1 50         if (now_ns > time->time_point_ns || delta_ns > time->time_point_ns) {
    50          
110 0           return AMQP_STATUS_INVALID_PARAMETER;
111             }
112              
113 1           return AMQP_STATUS_OK;
114             }
115              
116 66           int amqp_time_s_from_now(amqp_time_t *time, int seconds) {
117             uint64_t now_ns;
118             uint64_t delta_ns;
119 66 50         assert(NULL != time);
120              
121 66 50         if (0 >= seconds) {
122 66           *time = amqp_time_infinite();
123 66           return AMQP_STATUS_OK;
124             }
125              
126 0           now_ns = amqp_get_monotonic_timestamp();
127 0 0         if (0 == now_ns) {
128 0           return AMQP_STATUS_TIMER_FAILURE;
129             }
130              
131 0           delta_ns = (uint64_t)seconds * AMQP_NS_PER_S;
132 0           time->time_point_ns = now_ns + delta_ns;
133 0 0         if (now_ns > time->time_point_ns || delta_ns > time->time_point_ns) {
    0          
134 0           return AMQP_STATUS_INVALID_PARAMETER;
135             }
136              
137 0           return AMQP_STATUS_OK;
138             }
139              
140 68           amqp_time_t amqp_time_infinite(void) {
141             amqp_time_t time;
142 68           time.time_point_ns = UINT64_MAX;
143 68           return time;
144             }
145              
146 1           int amqp_time_ms_until(amqp_time_t time) {
147             uint64_t now_ns;
148             uint64_t delta_ns;
149             int left_ms;
150              
151 1 50         if (UINT64_MAX == time.time_point_ns) {
152 0           return -1;
153             }
154 1 50         if (0 == time.time_point_ns) {
155 0           return 0;
156             }
157              
158 1           now_ns = amqp_get_monotonic_timestamp();
159 1 50         if (0 == now_ns) {
160 0           return AMQP_STATUS_TIMER_FAILURE;
161             }
162              
163 1 50         if (now_ns >= time.time_point_ns) {
164 0           return 0;
165             }
166              
167 1           delta_ns = time.time_point_ns - now_ns;
168 1           left_ms = (int)(delta_ns / AMQP_NS_PER_MS);
169              
170 1           return left_ms;
171             }
172              
173 0           int amqp_time_tv_until(amqp_time_t time, struct timeval *in,
174             struct timeval **out) {
175             uint64_t now_ns;
176             uint64_t delta_ns;
177              
178 0 0         assert(in != NULL);
179 0 0         if (UINT64_MAX == time.time_point_ns) {
180 0           *out = NULL;
181 0           return AMQP_STATUS_OK;
182             }
183 0 0         if (0 == time.time_point_ns) {
184 0           in->tv_sec = 0;
185 0           in->tv_usec = 0;
186 0           *out = in;
187 0           return AMQP_STATUS_OK;
188             }
189              
190 0           now_ns = amqp_get_monotonic_timestamp();
191 0 0         if (0 == now_ns) {
192 0           return AMQP_STATUS_TIMER_FAILURE;
193             }
194              
195 0 0         if (now_ns >= time.time_point_ns) {
196 0           in->tv_sec = 0;
197 0           in->tv_usec = 0;
198 0           *out = in;
199 0           return AMQP_STATUS_OK;
200             }
201              
202 0           delta_ns = time.time_point_ns - now_ns;
203 0           in->tv_sec = (int)(delta_ns / AMQP_NS_PER_S);
204 0           in->tv_usec = (int)((delta_ns % AMQP_NS_PER_S) / AMQP_NS_PER_US);
205 0           *out = in;
206              
207 0           return AMQP_STATUS_OK;
208             }
209              
210 0           int amqp_time_has_past(amqp_time_t time) {
211             uint64_t now_ns;
212 0 0         if (UINT64_MAX == time.time_point_ns) {
213 0           return AMQP_STATUS_OK;
214             }
215              
216 0           now_ns = amqp_get_monotonic_timestamp();
217 0 0         if (0 == now_ns) {
218 0           return AMQP_STATUS_TIMER_FAILURE;
219             }
220              
221 0 0         if (now_ns > time.time_point_ns) {
222 0           return AMQP_STATUS_TIMEOUT;
223             }
224 0           return AMQP_STATUS_OK;
225             }
226              
227 1           amqp_time_t amqp_time_first(amqp_time_t l, amqp_time_t r) {
228 1 50         if (l.time_point_ns < r.time_point_ns) {
229 0           return l;
230             }
231 1           return r;
232             }
233              
234 0           int amqp_time_equal(amqp_time_t l, amqp_time_t r) {
235 0           return l.time_point_ns == r.time_point_ns;
236             }