Coverage Report

Created: 2023-03-26 06:05

/src/fluent-bit/src/flb_time.c
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*  Fluent Bit
4
 *  ==========
5
 *  Copyright (C) 2015-2022 The Fluent Bit Authors
6
 *
7
 *  Licensed under the Apache License, Version 2.0 (the "License");
8
 *  you may not use this file except in compliance with the License.
9
 *  You may obtain a copy of the License at
10
 *
11
 *      http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 *  Unless required by applicable law or agreed to in writing, software
14
 *  distributed under the License is distributed on an "AS IS" BASIS,
15
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 *  See the License for the specific language governing permissions and
17
 *  limitations under the License.
18
 */
19
20
#include "cmetrics/lib/mpack/src/mpack/mpack.h"
21
#include <msgpack.h>
22
#include <mpack/mpack.h>
23
#include <fluent-bit/flb_compat.h>
24
#include <fluent-bit/flb_macros.h>
25
#include <fluent-bit/flb_log.h>
26
#include <fluent-bit/flb_time.h>
27
#include <stdint.h>
28
#ifdef FLB_HAVE_CLOCK_GET_TIME
29
#  include <mach/clock.h>
30
#  include <mach/mach.h>
31
#endif
32
33
#include <string.h>
34
#include <inttypes.h>
35
#include <time.h>
36
37
0
#define ONESEC_IN_NSEC 1000000000
38
39
static int is_valid_format(int fmt)
40
0
{
41
0
    return (FLB_TIME_ETFMT_INT <= fmt) && (fmt < FLB_TIME_ETFMT_OTHER) ?
42
0
      FLB_TRUE : FLB_FALSE;
43
0
}
44
45
static int _flb_time_get(struct flb_time *tm)
46
0
{
47
0
    if (tm == NULL) {
48
0
        return -1;
49
0
    }
50
#if defined FLB_TIME_FORCE_FMT_INT
51
    tm->tm.tv_sec  = time(NULL);
52
    tm->tm.tv_nsec = 0;
53
    return 0;
54
#elif defined FLB_HAVE_TIMESPEC_GET
55
    /* C11 supported! */
56
0
    return timespec_get(&tm->tm, TIME_UTC);
57
#elif defined FLB_CLOCK_GET_TIME
58
    clock_serv_t cclock;
59
    mach_timespec_t mts;
60
    host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
61
    clock_get_time(cclock, &mts);
62
    tm->tv_sec = mts.tv_sec;
63
    tm->tv_nsec = mts.tv_nsec;
64
    return mach_port_deallocate(mach_task_self(), cclock);
65
#else /* __STDC_VERSION__ */
66
    return clock_gettime(CLOCK_REALTIME, &tm->tm);
67
#endif
68
0
}
69
70
int flb_time_get(struct flb_time *tm)
71
0
{
72
0
    return _flb_time_get(tm);
73
0
}
74
75
/* A portable function to sleep N msec */
76
int flb_time_msleep(uint32_t ms)
77
0
{
78
#ifdef _MSC_VER
79
    Sleep((DWORD) ms);
80
    return 0;
81
#else
82
0
    struct timespec ts;
83
0
    ts.tv_sec = ms / 1000;
84
0
    ts.tv_nsec = (ms % 1000) * 1000000;
85
0
    return nanosleep(&ts, NULL);
86
0
#endif
87
0
}
88
89
double flb_time_to_double(struct flb_time *tm)
90
0
{
91
0
    return (double)(tm->tm.tv_sec) + ((double)tm->tm.tv_nsec/(double)ONESEC_IN_NSEC);
92
0
}
93
94
uint64_t flb_time_to_nanosec(struct flb_time *tm)
95
0
{
96
0
    return (((uint64_t)tm->tm.tv_sec * 1000000000L) + tm->tm.tv_nsec);
97
0
}
98
99
uint64_t flb_time_to_millisec(struct flb_time *tm)
100
0
{
101
0
    return (((uint64_t)tm->tm.tv_sec * 1000L) + tm->tm.tv_nsec / 1000000L);
102
0
}
103
104
int flb_time_add(struct flb_time *base, struct flb_time *duration, struct flb_time *result)
105
0
{
106
0
    if (base == NULL || duration == NULL|| result == NULL) {
107
0
        return -1;
108
0
    }
109
0
    result->tm.tv_sec  = base->tm.tv_sec  + duration->tm.tv_sec;
110
0
    result->tm.tv_nsec = base->tm.tv_nsec + duration->tm.tv_nsec;
111
112
0
    if (result->tm.tv_nsec > ONESEC_IN_NSEC) {
113
0
        result->tm.tv_nsec -= ONESEC_IN_NSEC;
114
0
        result->tm.tv_sec++;
115
0
    } else if (result->tm.tv_nsec < 0) {
116
0
        result->tm.tv_nsec += ONESEC_IN_NSEC;
117
0
        result->tm.tv_sec--;
118
0
    }
119
120
0
    return 0;
121
0
}
122
123
int flb_time_diff(struct flb_time *time1,
124
                  struct flb_time *time0,struct flb_time *result)
125
0
{
126
0
    if (time1 == NULL || time0 == NULL || result == NULL) {
127
0
        return -1;
128
0
    }
129
130
0
    if (time1->tm.tv_sec >= time0->tm.tv_sec) {
131
0
        result->tm.tv_sec = time1->tm.tv_sec - time0->tm.tv_sec;
132
0
        if (time1->tm.tv_nsec >= time0->tm.tv_nsec) {
133
0
            result->tm.tv_nsec = time1->tm.tv_nsec - time0->tm.tv_nsec;
134
0
        }
135
0
        else if(result->tm.tv_sec == 0){
136
            /* underflow */
137
0
            return -1;
138
0
        }
139
0
        else{
140
0
            result->tm.tv_nsec = ONESEC_IN_NSEC
141
0
                               + time1->tm.tv_nsec - time0->tm.tv_nsec;
142
0
            result->tm.tv_sec--;
143
0
        }
144
0
    }
145
0
    else {
146
        /* underflow */
147
0
        return -1;
148
0
    }
149
0
    return 0;
150
0
}
151
152
int flb_time_append_to_mpack(mpack_writer_t *writer, struct flb_time *tm, int fmt)
153
0
{
154
0
    int ret = 0;
155
0
    struct flb_time l_time;
156
0
    char ext_data[8];
157
0
    uint32_t tmp;
158
159
0
    if (!is_valid_format(fmt)) {
160
#ifdef FLB_TIME_FORCE_FMT_INT
161
        fmt = FLB_TIME_ETFMT_INT;
162
#else
163
0
        fmt = FLB_TIME_ETFMT_V1_FIXEXT;
164
0
#endif
165
0
    }
166
167
0
    if (tm == NULL) {
168
0
      if (fmt == FLB_TIME_ETFMT_INT) {
169
0
         l_time.tm.tv_sec = time(NULL);
170
0
      }
171
0
      else {
172
0
        _flb_time_get(&l_time);
173
0
      }
174
0
      tm = &l_time;
175
0
    }
176
177
0
    switch(fmt) {
178
0
    case FLB_TIME_ETFMT_INT:
179
0
        mpack_write_uint(writer, tm->tm.tv_sec);
180
0
        break;
181
182
0
    case FLB_TIME_ETFMT_V0:
183
0
    case FLB_TIME_ETFMT_V1_EXT:
184
        /* We can't set with msgpack-c !! */
185
        /* see pack_template.h and msgpack_pack_inline_func(_ext) */
186
0
    case FLB_TIME_ETFMT_V1_FIXEXT:
187
0
        tmp = htonl((uint32_t)tm->tm.tv_sec); /* second from epoch */
188
0
        memcpy(&ext_data, &tmp, 4);
189
0
        tmp = htonl((uint32_t)tm->tm.tv_nsec);/* nanosecond */
190
0
        memcpy(&ext_data[4], &tmp, 4);
191
192
        /* https://github.com/fluent/fluentd/wiki/Forward-Protocol-Specification-v1#eventtime-ext-format */
193
0
        mpack_write_ext(writer, 0 /*ext type=0 */, ext_data, sizeof(ext_data));
194
0
        break;
195
196
0
    default:
197
0
        ret = -1;
198
0
    }
199
200
0
    return ret;
201
0
}
202
203
int flb_time_append_to_msgpack(struct flb_time *tm, msgpack_packer *pk, int fmt)
204
0
{
205
0
    int ret = 0;
206
0
    struct flb_time l_time;
207
0
    char ext_data[8];
208
0
    uint32_t tmp;
209
210
0
    if (!is_valid_format(fmt)) {
211
#ifdef FLB_TIME_FORCE_FMT_INT
212
        fmt = FLB_TIME_ETFMT_INT;
213
#else
214
0
        fmt = FLB_TIME_ETFMT_V1_FIXEXT;
215
0
#endif
216
0
    }
217
218
0
    if (tm == NULL) {
219
0
      if (fmt == FLB_TIME_ETFMT_INT) {
220
0
         l_time.tm.tv_sec = time(NULL);
221
0
      }
222
0
      else {
223
0
        _flb_time_get(&l_time);
224
0
      }
225
0
      tm = &l_time;
226
0
    }
227
228
0
    switch(fmt) {
229
0
    case FLB_TIME_ETFMT_INT:
230
0
        msgpack_pack_uint64(pk, tm->tm.tv_sec);
231
0
        break;
232
233
0
    case FLB_TIME_ETFMT_V0:
234
0
    case FLB_TIME_ETFMT_V1_EXT:
235
        /* We can't set with msgpack-c !! */
236
        /* see pack_template.h and msgpack_pack_inline_func(_ext) */
237
0
    case FLB_TIME_ETFMT_V1_FIXEXT:
238
0
        tmp = htonl((uint32_t)tm->tm.tv_sec); /* second from epoch */
239
0
        memcpy(&ext_data, &tmp, 4);
240
0
        tmp = htonl((uint32_t)tm->tm.tv_nsec);/* nanosecond */
241
0
        memcpy(&ext_data[4], &tmp, 4);
242
243
0
        msgpack_pack_ext(pk, 8/*fixext8*/, 0);
244
0
        msgpack_pack_ext_body(pk, ext_data, sizeof(ext_data));
245
246
0
        break;
247
248
0
    default:
249
0
        ret = -1;
250
0
    }
251
252
0
    return ret;
253
0
}
254
255
static inline int is_eventtime(msgpack_object *obj)
256
0
{
257
0
    if (obj->via.ext.type != 0 || obj->via.ext.size != 8) {
258
0
        return FLB_FALSE;
259
0
    }
260
0
    return FLB_TRUE;
261
0
}
262
263
int flb_time_msgpack_to_time(struct flb_time *time, msgpack_object *obj)
264
0
{
265
0
    uint32_t tmp;
266
267
0
    switch(obj->type) {
268
0
    case MSGPACK_OBJECT_POSITIVE_INTEGER:
269
0
        time->tm.tv_sec  = obj->via.u64;
270
0
        time->tm.tv_nsec = 0;
271
0
        break;
272
0
    case MSGPACK_OBJECT_FLOAT:
273
0
        time->tm.tv_sec  = obj->via.f64;
274
0
        time->tm.tv_nsec = ((obj->via.f64 - time->tm.tv_sec) * ONESEC_IN_NSEC);
275
0
        break;
276
0
    case MSGPACK_OBJECT_EXT:
277
0
        if (is_eventtime(obj) != FLB_TRUE) {
278
0
            flb_warn("[time] unknown ext type. type=%d size=%d",
279
0
                     obj->via.ext.type, obj->via.ext.size);
280
0
            return -1;
281
0
        }
282
0
        memcpy(&tmp, &obj->via.ext.ptr[0], 4);
283
0
        time->tm.tv_sec = (uint32_t) ntohl(tmp);
284
0
        memcpy(&tmp, &obj->via.ext.ptr[4], 4);
285
0
        time->tm.tv_nsec = (uint32_t) ntohl(tmp);
286
0
        break;
287
0
    default:
288
0
        flb_warn("unknown time format %x", obj->type);
289
0
        return -1;
290
0
    }
291
292
0
    return 0;
293
0
}
294
295
int flb_time_pop_from_mpack(struct flb_time *time, mpack_reader_t *reader)
296
0
{
297
0
    mpack_tag_t tag;
298
0
    double d;
299
0
    float f;
300
0
    int64_t i;
301
0
    uint32_t tmp;
302
0
    char extbuf[8];
303
0
    size_t ext_len;
304
305
0
    if (time == NULL) {
306
0
        return -1;
307
0
    }
308
309
0
    tag = mpack_read_tag(reader);
310
311
0
    if (mpack_reader_error(reader) != mpack_ok ||
312
0
        mpack_tag_type(&tag) != mpack_type_array ||
313
0
        mpack_tag_array_count(&tag) == 0) {
314
0
        return -1;
315
0
    }
316
317
0
    tag = mpack_read_tag(reader);
318
0
    switch (mpack_tag_type(&tag)) {
319
0
        case mpack_type_int:
320
0
            i = mpack_tag_int_value(&tag);
321
0
            if (i < 0) {
322
0
                flb_warn("expecting positive integer, got %" PRId64, i);
323
0
                return -1;
324
0
            }
325
0
            time->tm.tv_sec  = i;
326
0
            time->tm.tv_nsec = 0;
327
0
            break;
328
0
        case mpack_type_uint:
329
0
            time->tm.tv_sec  = mpack_tag_uint_value(&tag);
330
0
            time->tm.tv_nsec = 0;
331
0
            break;
332
0
        case mpack_type_float:
333
0
            f = mpack_tag_float_value(&tag);
334
0
            time->tm.tv_sec = f;
335
0
            time->tm.tv_nsec = ((f - time->tm.tv_sec) * ONESEC_IN_NSEC);
336
0
        case mpack_type_double:
337
0
            d = mpack_tag_double_value(&tag);
338
0
            time->tm.tv_sec  = d;
339
0
            time->tm.tv_nsec = ((d - time->tm.tv_sec) * ONESEC_IN_NSEC);
340
0
            break;
341
0
        case mpack_type_ext:
342
0
            ext_len = mpack_tag_ext_length(&tag);
343
0
            if (ext_len != 8) {
344
0
                flb_warn("expecting ext_len is 8, got %" PRId64, ext_len);
345
0
                return -1;
346
0
            }
347
0
            mpack_read_bytes(reader, extbuf, ext_len);
348
0
            memcpy(&tmp, extbuf, 4);
349
0
            time->tm.tv_sec = (uint32_t) ntohl(tmp);
350
0
            memcpy(&tmp, extbuf + 4, 4);
351
0
            time->tm.tv_nsec = (uint32_t) ntohl(tmp);
352
0
            break;
353
0
        default:
354
0
            flb_warn("unknown time format %d", tag.type);
355
0
            return -1;
356
0
    }
357
358
0
    return 0;
359
0
}
360
361
int flb_time_pop_from_msgpack(struct flb_time *time, msgpack_unpacked *upk,
362
                              msgpack_object **map)
363
0
{
364
0
    int ret;
365
0
    msgpack_object obj;
366
367
0
    if (time == NULL || upk == NULL) {
368
0
        return -1;
369
0
    }
370
371
0
    if (upk->data.type != MSGPACK_OBJECT_ARRAY) {
372
0
        return -1;
373
0
    }
374
375
0
    obj = upk->data.via.array.ptr[0];
376
0
    *map = &upk->data.via.array.ptr[1];
377
378
0
    ret = flb_time_msgpack_to_time(time, &obj);
379
0
    return ret;
380
0
}
381
382
long flb_time_tz_offset_to_second()
383
0
{
384
0
    time_t t = time(NULL);
385
0
    struct tm local = *localtime(&t);
386
0
    struct tm utc = *gmtime(&t);
387
388
0
    long diff = ((local.tm_hour - utc.tm_hour)          \
389
0
                 * 60 + (local.tm_min - utc.tm_min))    \
390
0
                 * 60L + (local.tm_sec - utc.tm_sec);
391
392
0
    int delta_day = local.tm_mday - utc.tm_mday;
393
394
0
    if ((delta_day == 1) || (delta_day < -1)) {
395
0
        diff += 24L * 60 * 60;
396
0
    }
397
0
    else if ((delta_day == -1) || (delta_day > 1)) {
398
0
        diff -= 24L * 60 * 60;
399
0
    }
400
401
0
    return diff;
402
0
}