GSoC Week 2 : Displays all loaded timers and calculates its next run time.

This week’s work was on the display of all loaded timers and calculation of its next run time and last run time. Request to have timer properties set via D-BUS was also filed to systemd last week. (https://github.com/systemd/systemd/issues/3234)

Calculation and creation of relative time stamps

The loaded timers can be listed out via the following command.

systemctl list-timers — all

This command displays loaded timers with next run time and time passed since last run. ( like 30min left and 29min ago ). I found the C code to it here https://github.com/systemd/systemd/blob/master/src/basic/time-util.c#L256 .

A JavaScript version of the systemd’s time conversion in C was created. It takes input in microseconds and outputs relative time-stamps.

Few examples :

format_timestamp_relative(1463509800000000) outputs “3h 60min left”.

format_timestamp_relative(1463499137000000) gives “49s ago”.

format_timestamp_relative(1463499167000) gives “46 years 3 months ago”.

Use Math.floor() to round to nearest integer for the results like here.

https://github.com/harishanand95/timer_mockup/blob/master/service.html#L147


Calculation of last run and next run time for timers using format_timestamp_relative function

  • To get Last Run (relative time) of a timer
var systemd_client = cockpit.dbus("org.freedesktop.systemd1", { superuser: "try" });
var systemd_timer = systemd_client.proxy("org.freedesktop.systemd1.Timer",
"/org/freedesktop/systemd1/unit/systemd_2dtmpfiles_2dclean_2etimer");
format_timestamp_relative(systemd_timer.LastTriggerUSec);
systemd_timer.LastTriggerUSec gives time in CLOCK_REALTIME. We give it to format_timestamp_relative() as such.
  • To get Next Run (relative time) of a timer

Next Run time values can be CLOCK_REALTIME (for Calendar timers) and CLOCK_MONOTONIC (for Monotonic timers).

That’s why, timer D-BUS provides two properties to get next run time:

NextElapseUSecMonotonic and NextElapseUSecRealtime
If we have a calendar timer set, then NextElapseUSecRealtime will give the timer’s next run time in CLOCK_REALTIME.
If we have a monotonic timer set, then NextElapseUSecMonotonic will give the monotonic time from system startup time to next run (i.e not from Jan 1 1970). So to get the real time, we must add GeneratorsStartTimestamp of the systemd_manager object.

( As mentioned in paragraph 5 here, monotonic timers start from kernel startup. So we need to add system startup time to monotonic time to convert it to a real clock time. Here we use GeneratorsStartTimestamp to get an approximate system startup time.)

  1. Connect to both timer (any) and the manager object.
var systemd_client = cockpit.dbus("org.freedesktop.systemd1", { superuser: "try" });
var systemd_manager =systemd_client.proxy("org.freedesktop.systemd1.Manager",
"/org/freedesktop/systemd1");
var systemd_timer 
=systemd_client.proxy("org.freedesktop.systemd1.Timer",
"/org/freedesktop/systemd1/unit/systemd_2dtmpfiles_2dclean_2etimer");

2. Use manager object to get GeneratorsStartTimestamp.

if (systemd_timer.NextElapseUSecMonotonic > 0) {
time = systemd_manager.GeneratorsStartTimestamp + systemd_timer.NextElapseUSecMonotonic;
}
else {
time = systemd_timer.NextElapseUSecRealtime;
}
console.log(time);
format_timestamp_relative(time);

Here is the link to the currently developing timer playground app and a screenshot .

Meanwhile I’m also learning JavaScript during this community bonding phase as I’m a beginner to it.