|
31 | 31 | #include <libmnl/libmnl.h> |
32 | 32 | #include <string.h> |
33 | 33 | #include <sys/time.h> |
| 34 | +#include <time.h> |
34 | 35 | #include <stdlib.h> |
35 | 36 | #include <errno.h> |
36 | 37 | #include <sqlite3.h> |
| 38 | +#include <linux/sysinfo.h> |
| 39 | +#include <sys/syscall.h> |
37 | 40 |
|
38 | 41 | #include "metadata_writer_sqlite.h" |
39 | 42 | #include "metadata_writer_inventory_conn.h" |
@@ -295,27 +298,51 @@ static sqlite3* md_sqlite_configure_db(struct md_writer_sqlite *mws, const char |
295 | 298 | return db_handle; |
296 | 299 | } |
297 | 300 |
|
298 | | -static int md_sqlite_read_boot_time(struct md_writer_sqlite *mws, uint64_t *boot_time) |
| 301 | +static int md_sqlite_read_orig_boot_time(struct md_writer_sqlite *mws) |
299 | 302 | { |
300 | | - struct timeval tv; |
301 | | - uint64_t uptime; |
| 303 | + struct timespec tp_raw, tp_real; |
| 304 | + struct sysinfo info = {0}; |
302 | 305 |
|
303 | | - //read uptime |
304 | | - if (system_helpers_read_uint64_from_file("/proc/uptime", &uptime)) { |
305 | | - return RETVAL_FAILURE; |
306 | | - } |
| 306 | + syscall(SYS_sysinfo, &info); |
307 | 307 |
|
308 | | - gettimeofday(&tv, NULL); |
| 308 | + clock_gettime(CLOCK_MONOTONIC_RAW, &tp_raw); |
| 309 | + clock_gettime(CLOCK_REALTIME, &tp_real); |
309 | 310 |
|
310 | | - *boot_time = tv.tv_sec - uptime; |
311 | | - |
312 | | - if (*boot_time < mws->orig_boot_time) { |
313 | | - return RETVAL_FAILURE; |
| 311 | + //This can only happen on boot on devices where time is reset to epoch. |
| 312 | + //uptime and clock_gettime() come from different clock sources, uptime might |
| 313 | + //for example have been updated before tp_real |
| 314 | + if (info.uptime > tp_real.tv_sec) { |
| 315 | + mws->orig_boot_time = 0; |
| 316 | + } else { |
| 317 | + mws->orig_boot_time = tp_real.tv_sec - info.uptime; |
314 | 318 | } |
315 | 319 |
|
| 320 | + mws->orig_uptime = info.uptime; |
| 321 | + mws->orig_raw_time = tp_raw.tv_sec; |
| 322 | + |
316 | 323 | return RETVAL_SUCCESS; |
317 | 324 | } |
318 | 325 |
|
| 326 | +static void md_sqlite_get_real_boot_time(struct md_writer_sqlite *mws, uint64_t *real_boot_time) |
| 327 | +{ |
| 328 | + struct timespec tp_raw, tp_real; |
| 329 | + |
| 330 | + clock_gettime(CLOCK_MONOTONIC_RAW, &tp_raw); |
| 331 | + clock_gettime(CLOCK_REALTIME, &tp_real); |
| 332 | + |
| 333 | + //The calculation here is as follows: |
| 334 | + //* The goal is to find the correct boot time, now that we have a valid NTP fix |
| 335 | + //* We get the current (walltime). |
| 336 | + //* From this value we want to subtract the total uptime. |
| 337 | + //* To reduce the number of clock sources, we use use MONOTONIG_RAW to calculate |
| 338 | + //the amount of time that has passed since data_exporter was started. |
| 339 | + //* We add the diff between (cur_raw - orig_raw) to the uptime we read when |
| 340 | + //data_exporter was started. The sum is time elapsed since boot. |
| 341 | + //* In order to get the "correct" boot time, we subtract the calculation above |
| 342 | + //from the current walltime. |
| 343 | + *real_boot_time = tp_real.tv_sec - (mws->orig_uptime + (tp_raw.tv_sec - mws->orig_raw_time)); |
| 344 | +} |
| 345 | + |
319 | 346 | static int md_sqlite_configure(struct md_writer_sqlite *mws, |
320 | 347 | const char *db_filename, uint32_t node_id, uint32_t db_interval, |
321 | 348 | uint32_t db_events, const char *meta_prefix, const char *gps_prefix, |
@@ -466,7 +493,7 @@ static int md_sqlite_configure(struct md_writer_sqlite *mws, |
466 | 493 | system_helpers_read_uint64_from_file(mws->last_conn_tstamp_path, |
467 | 494 | &(mws->dump_tstamp)); |
468 | 495 |
|
469 | | - return md_sqlite_read_boot_time(mws, &(mws->orig_boot_time)); |
| 496 | + return md_sqlite_read_orig_boot_time(mws); |
470 | 497 | } |
471 | 498 |
|
472 | 499 | void md_sqlite_usage() |
@@ -575,13 +602,12 @@ static uint8_t md_sqlite_check_valid_tstamp(struct md_writer_sqlite *mws) |
575 | 602 |
|
576 | 603 | gettimeofday(&tv, NULL); |
577 | 604 |
|
578 | | - if (mws->ntp_fix_file[0] && access(mws->ntp_fix_file, F_OK)) |
579 | | - return RETVAL_FAILURE; |
580 | | - |
581 | | - if (md_sqlite_read_boot_time(mws, &real_boot_time)) { |
| 605 | + if (mws->ntp_fix_file[0] && access(mws->ntp_fix_file, F_OK)) { |
582 | 606 | return RETVAL_FAILURE; |
583 | 607 | } |
584 | 608 |
|
| 609 | + md_sqlite_get_real_boot_time(mws, &real_boot_time); |
| 610 | + |
585 | 611 | META_PRINT_SYSLOG(mws->parent, LOG_INFO, "Real boot %" PRIu64 " orig boot %" PRIu64 "\n", real_boot_time, mws->orig_boot_time); |
586 | 612 |
|
587 | 613 | if (md_sqlite_update_timestamp_db(mws, UPDATE_EVENT_TSTAMP, |
|
0 commit comments