From 3534b428629be185e096be99e3bd5fdfe32d5544 Mon Sep 17 00:00:00 2001 From: Laurent Bercot Date: Thu, 18 Sep 2014 18:55:44 +0000 Subject: initial commit with rc for skalibs-2.0.0.0 --- doc/libstddjb/tai.html | 462 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 462 insertions(+) create mode 100644 doc/libstddjb/tai.html (limited to 'doc/libstddjb/tai.html') diff --git a/doc/libstddjb/tai.html b/doc/libstddjb/tai.html new file mode 100644 index 0000000..3524c05 --- /dev/null +++ b/doc/libstddjb/tai.html @@ -0,0 +1,462 @@ + + + + + skalibs: the tai library interface + + + + + + +

+libstddjb
+libskarnet
+skalibs
+Software
+skarnet.org +

+ +

The tai library interface

+ +

+ The following functions are declared in the skalibs/tai.h header, +and implemented in the libskarnet.a or libskarnet.so library. +

+ +

General information

+ +

+ tai is a set of data structures and primitives to represent +and perform operations on time. +

+ +

+ The point of tai is to handle time without ever having to +deal with annoyances such as Y2K, Y2038, NTP limits, non-linear +clocks, and the like. By using the tai interface, you ensure +your program will behave properly no matter what. +

+ +

What is the problem ?

+ +

+ The standard APIs for time management under Unix are broken in more +or less subtle ways. The most obvious thing is that they do not pass +year 2038. A less obvious problem is that they do not handle leap +seconds correctly. Here are a few references you should read to +understand what is going on: +

+ + + +

+ The meat and potatoes of all this is that programmers cannot simply rely on +standard Unix APIs such as +gettimeofday() +(which, by the way, is marked as obsolescent, but it's not going to disappear tomorrow) +to measure time intervals or even to give precise absolute time, and in +any case those APIs will become obsolete in 2038. +

+ +

So what does tai do ?

+ +

+ tai implements - among other things - the +TAI64 and TAI64N +formats, which are used in all of skalibs. This gives a programmer access +to precise linear absolute time, which is suitable for both +timestamping (wallclock usage) and time interval measurements +(stopwatch usage). Additionally, TAI64 passes Y2038 (it can +represent dates exceeding the estimated lifespan of the universe). +

+ +

+ tai has been inspired by Dan J. Bernstein's +libtai library, but does not +borrow any code from it. +

+ +

Data structures

+ +

+ A tai_t structure holds an absolute date with a one-second +precision. A tain_t structure holds an absolute date with a +maximum of one-nanosecond precision, as permitted by the underlying system +call. If flag-usert is clear, the system +clock will be read via +gettimeofday() +system call, which has a one-microsecond precision; if it is set, the +system clock will be read via the +clock_gettime() +system call, which has a one-nanosecond precision. In either case, a current +tain_t will be unable to be more precise than the underlying +implementation. +

+ +

+ A tai_t, as well as a tain_t, can also +hold a (possibly negative) relative time, i.e. a difference of absolute +dates. It is up to the programmer to make sure that a relative time is +never interpreted as an absolute TAI64 date, and vice-versa. +

+ +

The leap second table

+ +

+ skalibs provides a src/etc/leapsecs.dat file, +which is copied to /etc/leapsecs.dat at installation time +(or wherever you specified with the --prefix or --datadir +options to configure). +Make sure this file is always present and readable. +This file contains the leap second table, which is needed for +conversions between TAI and UTC. If you call a function that needs such +a conversion (for instance, you call tain_sysclock() and your +system clock is set to UTC) and the file cannot be read, the function +call will fail. +

+ +

+ The leap second table is read once in every process that needs it +(the first time a TAI ↔ UTC conversion is made) and then is +stored in memory. If the leapsecs.dat file changes, long-lived +processes will need to be restarted to take the change into account. +

+ +

Functions

+ +

Wallclock operations

+ +

+ int tai_now (tai_t *t)
+Writes the current time as a TAI value to *t, with a +1-second precision. The current time is based on the system clock. +Make sure skalibs has been compiled with or without the +--enable-tai-clock configure option according +to your system clock synchronization method: skalibs supports a +system clock set to TAI-10 or to UTC. +The function returns 1 if it succeeds, or 0 (and sets errno) if +it fails. +

+ +

+ int sysclock_get (tain_t *a)
+Reads the current value of the system clock into *a, with +a 1-nanosecond (resp. 1-microsecond ) precision if skalibs has been +configured with (resp. without) the +--enable-clock option. +Returns 1 if it succeeds or 0 (and sets errno) if it +fails. Note that despite being a tain_t, *a +does not contain a TAI value - it only contains +an internal, Y2038-safe representation of the value of the system +clock, which should be either TAI-10 or UTC. You should not use +this function directly unless you know exactly what you are doing. +

+ +

+ int sysclock_set (tain_t const *a)
+Sets the system clock to *a, provided *a has +the correct internal representation. You should not use this +function directly unless you know exactly what you are doing. +

+ +

+ int tain_sysclock (tain_t *a)
+Reads the current time into *a, as a TAI64N value, +with a 1-nanosecond (resp. 1-microsecond) precision if skalibs +has been configured with (resp. without) the +--enable-clock +option. Returns 1 if it succeeds or 0 (and sets errno) if it +fails. + Here a contains a valid TAI stamp, no matter what the +system clock is set to: arithmetic operations can be performed +on it. +

+ +

+ int tain_setnow (tain_t const *a)
+Sets the current time to *a, with a 1-nanosecond +(resp. 1-microsecond) precision if skalibs has been configured +with (resp. without) the +--enable-clock +option. Returns 1 if it succeeds or 0 (and sets errno) if it +fails. a must contain a valid TAI stamp; proper +operations will be automatically run to convert that stamp into +the right format for the system clock. +

+ +

Stopwatch operations

+ +

+ The following 3 operations are only defined if your system +provides the +clock_gettime() +primitive with the CLOCK_MONOTONIC option. +

+ +

+ int tain_clockmon_init (tain_t *offset)
+Initializes a stopwatch in *offset. The actual value of +*offset is meaningless to the user; offset's only +use is to be given as a second parameter to tain_clockmon(). +The function returns 1 if it succeeds or 0 (and sets errno) if it fails. +

+ +

+ What tain_clockmon_init() does is synchronize the "stopwatch +clock" (CLOCK_MONOTONIC) to the system clock. Right after +tain_clockmon_init() has been called, the absolute times given +by tain_clockmon() and tain_sysclock() are similar. Then, +depending on the accuracy of the system clock, a drift may appear; calling +tain_clockmon_init() again resets that drift to zero. +

+ +

+ int tain_clockmon (tain_t *a, tain_t const *offset)
+ Gives the absolute time, as a TAI64N value, in *a. This +absolute time is computed as a linear increase (as measured with +CLOCK_MONOTONIC) since the last time tain_clockmon_init() +was called with parameter offset. tain_clockmon() +guarantees precise time interval measurements; however, the time it +gives can slightly differ from the result of tain_sysclock(). +The function returns 1 if it succeeds or 0 (and sets errno) if it fails. +

+ +

All-purpose time reading

+ +

+ int tain_init (void)
+If skalibs has been configured with the +--enable-monotonic option: this +function initializes a process-global stopwatch, that future +tain_now invocations will depend on. +Without the --enable-monotonic option: this +function does nothing. +The function returns 1 if it succeeds or 0 (and sets errno) if it fails. +

+ +

+ int tain_now (tain_t *a)
+Writes the current time, as a TAI value, to *a. This is the +function you should use to read time by default. It returns 1 if it succeeds or +0 (and sets errno) if it fails. +

+ +

+ If skalibs has been configured with the +--enable-monotonic option: +tain_now() is computed as a linear increase from the last time +tain_init() was called. (If tain_init() has never +been called before, the first invocation of tain_now() +automatically calls tain_init().) + Without the --enable-monotonic option: +tain_now() is the same as tain_sysclock(). +

+ +

+ If the above is unclear to you: just use tain_now() +everytime you need to read time, and you will always get a reasonable +approximation of the current time, in a format suited for arithmetic +computations. +

+ +

Converting to/from libc representations

+ +

+ int tai_from_timeval (tai_t *t, struct timeval const *tv)
+int tai_from_timespec (tai_t *t, struct timespec const *ts)
+int tai_relative_from_timeval (tai_t *t, struct timeval const *tv)
+int tai_relative_from_timespec (tai_t *t, struct timespec const *ts)

+Those functions convert an absolute (resp. relative) time in a +struct timeval (resp. struct timespec) to an absolute (resp. relative) +time in a tai_t, with a 1-second precision. They return 1. +

+ +

+ int timeval_from_tai (struct timeval *tv, tai_t const *t)
+int timespec_from_tai (struct timespec *ts, tai_t const *t)
+int timeval_from_tai_relative (struct timeval *tv, tai_t const *t)
+int timespec_from_tai_relative (struct timespec *ts, tai_t const *t)

+Those functions do the opposite conversion. They normally return 1; +however, struct timeval and struct timespec cannot +represent an absolute date before the Epoch, or a negative relative time; +if *t cannot be converted, 0 EINVAL is returned. +

+ +

+ int tain_from_timeval (tain_t *a, struct timeval const *tv)
+int tain_from_timespec (tain_t *a, struct timespec const *ts)
+int tain_relative_from_timeval (tain_t *a, struct timeval const *tv)
+int tain_relative_from_timespec (tain_t *a, struct timespec const *ts)
+int timeval_from_tain (struct timeval *tv, tain_t const *a)
+int timespec_from_tain (struct timespec *ts, tain_t const *a)
+int timeval_from_tain_relative (struct timeval *tv, tain_t const *a)
+int timespec_from_tain_relative (struct timespec *ts, tain_t const *a)

+Same conversion operations, but with a tain_t. The 1-microsecond +(for struct timeval) or 1-nanosecond (for struct timespec) +precision is preserved. +

+ +

+ void tain_uint (tain_t *a, unsigned int c)
+Stores a relative time of c seconds into a. +

+ +

+ int tain_from_millisecs (tain_t *a, int ms)
+This function makes a tain_t representing a relative +time of ms milliseconds. ms must be non-negative. +The function returns 1, unless ms is negative, in which case +it returns 0 EINVAL. +

+ +

+ int tain_to_millisecs (tain_t const *a)
+If *a contains a non-negative relative time that fits into +a 31-bit integer number of milliseconds, the function returns that +number. Else it returns -1 EINVAL. +

+ +

Time computations

+ +

+ void tai_add (tai_t *t, tai_t const *t1, tai_t const *t2)
+Stores *t1 + *t2 into t. Of course, *t1 +and *t2 must not both represent absolute times. +

+ +

+ void tai_sub (tai_t *t, tai_t const *t1, tai_t const *t2)
+Stores *t1 - *t2 into t. Of course, *t1 +and *t2 must be of the same type (relative or absolute), and +*t will always be relative. +

+ +

+ void tain_add (tain_t *a, tain_t const *a1, tain_t const *a2)
+void tain_sub (tain_t *a, tain_t const *a1, tain_t const *a2)

+Same thing with tain_t. +

+ +

+ void tain_addsec (tain_t *a, tain_t const *a1, int c)
+Adds c seconds to *a1 and stores the result into a. +c may be negative. +

+ +

+ void tain_half (tain_t *a, tain_t const *b)
+Stores *b/2 into a. *b must be relative. +

+ +

Comparing dates or durations

+ +

+ int tai_less (tai_t const *t1, tai_t const *t2)
+int tain_less (tain_t const *t1, tain_t const *t2)

+Those functions return nonzero iff *t1 is lesser than *t2. +*t1 and *t2 must be both relative, or both absolute. +

+ +

Packing and unpacking

+ +

+ void tai_pack (char *s, tai_t const *t)
+Marshals *t into the buffer s points to, which +must be preallocated with at least TAI_PACK (8) characters. Afterwards, +the buffer contains the +external TAI64 format +representation of *t. +

+ +

+ void tai_unpack (char const *s, tai_t *t)
+Unmarshals the +external TAI64 format +label pointed to by s (at least TAI_PACK characters) and stores +the result into t. +

+ +

+ void tain_pack (char *s, tain_t const *a)
+void tain_unpack (char const *s, tain_t *a)
+void tain_pack (char *s, tain_t const *a)
+void tain_unpack (char const *s, tain_t *a)

+Same thing with +external TAI64N format, +using TAIN_PACK (12) characters. +

+ +

Formatting and scanning

+ +

+ unsigned int tain_fmt (char *s, tain_t const *a)
+Writes into s an ASCII representation of *a in external +TAI64N format. s must point to a preallocated buffer of at least +TAIN_PACK*2 (24) characters. The function returns the number of bytes that +have been written to s (24). +

+ +

+ unsigned int tain_scan (char const *s, tain_t *a)
+Reads 24 characters from s; if those characters are a valid ASCII +representation of the external TAI64N format of some time value, this value +is stored into a, and 24 is returned. Else 0 is returned. +

+ +

Timestamping

+ +

+ A TAI64N timestamp is a string of 25 characters: a single '@' +character followed by the ASCII representation of the TAI64N external +format of an absolute date. +

+ +

+ unsigned int timestamp_fmt (char *s, tain_t const *a)
+Writes a TAI64N timestamp representing the absolute date *a +into the 25 characters pointed to by s. Returns 25. +

+ +

+ unsigned int timestamp_scan (char const *s, tain_t *a)
+Reads 25 characters at s. If those characters are a valid TAI64N +timestamp, stores the absolute date in a and returns 25. Else, +returns 0. +

+ +

+ int timestamp (char *s)
+Writes the current time (read from the system clock) as a TAI64N timestamp +into s. Returns 1 if it succeeds or 0 (and sets errno) if it fails. +

+ +

+ TAI64N timestamps are an efficient, robust, and easy-to-use way of +timestampping log lines. They're easy to recognize in automatic data +parsers. Log files where every line starts with a TAI64N timestamp can +be merged and alphanumerically sorted: the resulting file will be +chronologically sorted. +

+ +

+ The s6 package +provides tools to convert TAI64N timestamps into human-readable +dates. Please do not embed human-readable dates in your log files, +thus making parsing tools unnecessarily hard to write; +use TAI64N timestamps instead, design tools that can parse them, +and translate them to human-readable form at human analysis time. +

+ + + -- cgit v1.2.3