Documentation ¶
Overview ¶
Default time organizer
Helper function that does initialization that is good enough for many use cases ¶
Helper functions for checking RTC status.
Checking is linux wall clock in sync depends on installation and hardware configuration. Initial guess is that Adjtimex should work.
Please add functions for checking synchronization status in some other methods ¶
TimeGopher ¶
AJATUS 18.7.2022 Talletetaan RTC kellosync mukaan jos sync
AJATUS 19.7.2022 Voisiko joitain funktioita laittaa erikseen? Jotta helpompi testattavuus
This module provides uptime.
"Algorithm" is based on fact that golang time.Time includes "hidden" monotonic clock that is used when doing time operations like diff. https://pkg.go.dev/time#hdr-Monotonic_Clocks So it is possible to resolve what time.Time uptime. Assuming that it happens after latest kernel boot (uptime 0). For resolving older uptimes from timestamps, other methods and rtc sync history is needed
/proc/uptime have 0.01s granularity meaning that anything happening more frequently than 100Hz will have repeating timestamps
Index ¶
- Constants
- func FirstCallAfterBoot(flagfilename string) (bool, error)
- func RtcIsSynced_adjtimex() (bool, error)
- type NsEpoch
- type NsUptime
- type TimeFileDb
- func (p *TimeFileDb) All() ([]TimeVariable, error)
- func (p *TimeFileDb) GetFirstN(n int) ([]TimeVariable, error)
- func (p *TimeFileDb) GetLatestN(n int) ([]TimeVariable, error)
- func (p *TimeFileDb) GetOnBoot(boot int32) ([]TimeVariable, error)
- func (p *TimeFileDb) Insert(t TimeVariable) error
- func (p *TimeFileDb) Len() (int, error)
- func (p *TimeFileDb) SearchTimeVariable(epoch NsEpoch) (TimeVariable, error)
- func (p *TimeFileDb) SolveBootNumber(epoch NsEpoch) (int32, error)
- func (p *TimeFileDb) SolveEpoch(boot int32, uptime NsUptime) (NsEpoch, error)
- type TimeGopher
- func (p *TimeGopher) Convert(t time.Time) (TimeVariable, error)
- func (p *TimeGopher) DoUncertainTimeSync(t time.Time) error
- func (p *TimeGopher) DoUncertainTimeSyncNow() error
- func (p *TimeGopher) GetLatestTime() (TimeVariable, error)
- func (p *TimeGopher) IsColdStart() bool
- func (p *TimeGopher) Refresh(t time.Time, inSync bool) error
- func (p *TimeGopher) RefreshNow() error
- func (p *TimeGopher) RtcDeviation(t time.Time) (NsEpoch, error)
- func (p *TimeGopher) SolveTime(boot int32, uptime NsUptime) (time.Time, error)
- func (p *TimeGopher) Unconvert(tv TimeVariable) (time.Time, error)
- type TimeVariable
- func (p *TimeVariable) After(u TimeVariable) bool
- func (p *TimeVariable) Before(u TimeVariable) bool
- func (p *TimeVariable) Equal(u TimeVariable) bool
- func (p *TimeVariable) SolveEpoch(bootNumber int32, uptime NsUptime) (NsEpoch, error)
- func (p *TimeVariable) SolveUptime(bootNumber int32, epoch NsEpoch) (NsUptime, error)
- func (p *TimeVariable) ToBinary(storeRTC bool) ([]byte, error)
- type TimeVariableList
- func (p *TimeVariableList) GetFirstsInBoot() TimeVariableList
- func (p *TimeVariableList) GetVariablesInBoot(boot int32) TimeVariableList
- func (e TimeVariableList) Len() int
- func (e TimeVariableList) Less(i, j int) bool
- func (p *TimeVariableList) SearchTimeVariable(epoch NsEpoch) (TimeVariable, error)
- func (p *TimeVariableList) SolveBootNumber(epoch NsEpoch) (int32, error)
- func (p *TimeVariableList) SolveEpoch(bootNumber int32, uptime NsUptime) (NsEpoch, error)
- func (p TimeVariableList) String() string
- func (e TimeVariableList) Swap(i, j int)
- type UptimeChecker
Constants ¶
const ( DEFAULTDBFILE_UNCERTAINRTC = "uncertain.rtc" DEFAULTDBFILE_RTC = "rtcsync.rtc" DEFAULTDBFILE_STARTLOG = "start.time" DEFAULTDBFILE_STOPLOG = "stop.time" DEFAULTDBFILE_ALIVELOG = "alive.time" )
const ( WARMSTARTFILE = "/tmp/warmstart" WARMSTARTCONTENT = "warm start" )
const ( RECORDSIZE_TIMEVARIABLE_NORTC = 12 RECORDSIZE_TIMEVARIABLE_RTC = 20 )
const ( TIME_OK = iota //Clock synchronized, no leap second adjustment pending. TIME_INS //Indicates that a leap second will be added at the end of the UTC day TIME_DEL //Indicates that a leap second will be deleted at the end of the UTC day. TIME_OOP //Insertion of a leap second is in progress. TIME_WAIT // A leap-second insertion or deletion has been completed. This value will be returned until the next ADJ_STATUS operation clears the STA_INS and STA_DEL flags. TIME_ERROR )
https://man7.org/linux/man-pages/man2/adjtimex.2.html
const ( STA_PLL = 0x0001 /* enable PLL updates (rw) */ STA_PPSFREQ = 0x0002 /* enable PPS freq discipline (rw) */ STA_PPSTIME = 0x0004 /* enable PPS time discipline (rw) */ STA_FLL = 0x0008 /* select frequency-lock mode (rw) */ STA_INS = 0x0010 /* insert leap (rw) */ STA_DEL = 0x0020 /* delete leap (rw) */ STA_UNSYNC = 0x0040 /* clock unsynchronized (rw) */ STA_FREQHOLD = 0x0080 /* hold frequency (rw) */ STA_PPSSIGNAL = 0x0100 /* PPS signal present (ro) */ STA_PPSJITTER = 0x0200 /* PPS signal jitter exceeded (ro) */ STA_PPSWANDER = 0x0400 /* PPS signal wander exceeded (ro) */ STA_PPSERROR = 0x0800 /* PPS signal calibration error (ro) */ STA_CLOCKERR = 0x1000 /* clock hardware fault (ro) */ STA_NANO = 0x2000 /* resolution (0 = us, 1 = ns) (ro) */ STA_MODE = 0x4000 /* mode (0 = PLL, 1 = FLL) (ro) */ STA_CLK = 0x8000 /* clock source (0 = A, 1 = B) (ro) */ )
const EPOCH70S = 10 * 365 * 24 * 60 * 60 * 1000 * 1000 * 1000
Used for sanity check, was a joke at first
const (
PROCUPTIME = "/proc/uptime"
)
Variables ¶
This section is empty.
Functions ¶
func FirstCallAfterBoot ¶
FirstStartAfterBoot, helper function. Call and tell is this the first time. Creates file.
func RtcIsSynced_adjtimex ¶
RtcIsSynced_adjtimex uses syscall.Adjtimex for checking is wall clock synchronized
Types ¶
type NsEpoch ¶
type NsEpoch int64
type TimeFileDb ¶
type TimeFileDb struct {
// contains filtered or unexported fields
}
func CreateTimeFileDb ¶
func CreateTimeFileDb(storage fixregsto.FixRegSto, storeRTC bool) (TimeFileDb, error)
CreateTimeFileDb restores content from FixRegSto storage and initializes TimeFileDb struct
func (*TimeFileDb) All ¶
func (p *TimeFileDb) All() ([]TimeVariable, error)
func (*TimeFileDb) GetFirstN ¶
func (p *TimeFileDb) GetFirstN(n int) ([]TimeVariable, error)
func (*TimeFileDb) GetLatestN ¶
func (p *TimeFileDb) GetLatestN(n int) ([]TimeVariable, error)
func (*TimeFileDb) GetOnBoot ¶
func (p *TimeFileDb) GetOnBoot(boot int32) ([]TimeVariable, error)
func (*TimeFileDb) Insert ¶
func (p *TimeFileDb) Insert(t TimeVariable) error
func (*TimeFileDb) Len ¶
func (p *TimeFileDb) Len() (int, error)
func (*TimeFileDb) SearchTimeVariable ¶
func (p *TimeFileDb) SearchTimeVariable(epoch NsEpoch) (TimeVariable, error)
func (*TimeFileDb) SolveBootNumber ¶
func (p *TimeFileDb) SolveBootNumber(epoch NsEpoch) (int32, error)
Search vs solve
func (*TimeFileDb) SolveEpoch ¶
func (p *TimeFileDb) SolveEpoch(boot int32, uptime NsUptime) (NsEpoch, error)
type TimeGopher ¶
type TimeGopher struct { RtcMaxDeviation NsEpoch //deviation in nanosecond from RTC when in sync. Set variable default value if need to change settings UncertainRtcSyncLog *TimeFileDb //For manual sync RtcSyncLog *TimeFileDb StartLog *TimeFileDb //boot number and uptime StopLog *TimeFileDb //boot number and uptime needed LastLog *TimeFileDb //Last alive situation UptimeCheck *UptimeChecker //Create externally, better for testing // contains filtered or unexported fields }
func CreateDefaultTimeGopher ¶
func CreateDefaultTimeGopher(rtcLogDir string, latestKnowTimeElsewhere TimeVariable) (TimeGopher, error)
Create default that is good for embedded linux use This function acts also as example use Not possible to unit test well.
func NewTimeGopher ¶
func NewTimeGopher( timeNow time.Time, inSync bool, coldStart bool, rtcSyncLog *TimeFileDb, uncertainRtcSyncLog *TimeFileDb, startLog *TimeFileDb, stopLog *TimeFileDb, lastLog *TimeFileDb, latestKnowTimeElsewhere TimeVariable, uptimeCheck *UptimeChecker, ) (TimeGopher, error)
Parameters:
timeNow, give time.Now() as parameter inSync, set true if system time is synchronized when TimeGopher is created. Resolve for example with RtcIsSynced_adjtimex() coldStart, set true if first start. Resolve this for example with FirstCallAfterBoot(WARMSTARTFILE) rtcSyncLog, TimeFileDb pointer for storing certain sync events uncertainRtcSyncLog, TimeFileDb pointer for storing uncertain sync events. Nil if not needed startLog TimeFileDb, TimeFileDb pointer for storing entries when software starts (colds and warms). Nil if not needed stopLog TimeFileDb, TimeFileDb pointer for storing entries when software stops (entries added at next TimeGopher init). Nil if not needed lastLog TimeFileDb, TimeFileDb pointer for keeping up situation status when sofware was running latestKnowTimeElsewhere TimeVariable, //If some other time stamp information is kept outside TimeGopher, get latest entry here uptimeCheck, Pointer for uptime checker. There can be many implementations depeding on needs. (or unit test requires dummy version)
func (*TimeGopher) Convert ¶
func (p *TimeGopher) Convert(t time.Time) (TimeVariable, error)
Convert time at current boot to TimeVariable
func (*TimeGopher) DoUncertainTimeSync ¶
func (p *TimeGopher) DoUncertainTimeSync(t time.Time) error
UncertainTimeSync called by library user, after realtime clock is set from unreliable source like set manually This function adds time to uncertain RTC sync log. Uncertain sync is used if certain sync is not available
func (*TimeGopher) DoUncertainTimeSyncNow ¶
func (p *TimeGopher) DoUncertainTimeSyncNow() error
DoUncertainTimeSyncNow is helper function for calling DoUncertainTimeSync
func (*TimeGopher) GetLatestTime ¶
func (p *TimeGopher) GetLatestTime() (TimeVariable, error)
GetLatestTime picks the last entry of any TimeFileDb entry inside TimeGopher instance. Used internally and for diagnostics
func (*TimeGopher) IsColdStart ¶
func (p *TimeGopher) IsColdStart() bool
IsColdStart() returns true if TimeOrganized have created at first time after boot One use for this function is for checking, is there need to do something "after boot" on system
func (*TimeGopher) Refresh ¶
func (p *TimeGopher) Refresh(t time.Time, inSync bool) error
Refresh function is called as often as application requires. Calling frequently creates frequent synclog entries so determining when sofware was running
func (*TimeGopher) RefreshNow ¶
func (p *TimeGopher) RefreshNow() error
RefreshNow is helper function for Refresh
func (*TimeGopher) RtcDeviation ¶
func (p *TimeGopher) RtcDeviation(t time.Time) (NsEpoch, error)
RtcDeviation gets RTC deviation now. Deviation can happen if timekeeping jumps Based on this, decide is RTC update needed
func (*TimeGopher) Unconvert ¶
func (p *TimeGopher) Unconvert(tv TimeVariable) (time.Time, error)
Unconvert converts TimeVariable to time.Time, vased on what is synchronization is added. Helper function for SolveTime
type TimeVariable ¶
TimeVariable is way to store timestamps. Epoch can solved by know TimeVariables with same bootNumber
func ParseTimeVariable ¶
func ParseTimeVariable(raw []byte, storeRTC bool) (TimeVariable, error)
ParseTimeVariable parses TimeVariable from binary format
func (*TimeVariable) After ¶
func (p *TimeVariable) After(u TimeVariable) bool
After reports whether the TimeVariable instant p is after u.
func (*TimeVariable) Before ¶
func (p *TimeVariable) Before(u TimeVariable) bool
After reports whether the TimeVariable instant p is before u.
func (*TimeVariable) Equal ¶
func (p *TimeVariable) Equal(u TimeVariable) bool
Equal reports whether p and u are equal
func (*TimeVariable) SolveEpoch ¶
func (p *TimeVariable) SolveEpoch(bootNumber int32, uptime NsUptime) (NsEpoch, error)
SolveEpoch calculates propotional epoch from uptime
func (*TimeVariable) SolveUptime ¶
func (p *TimeVariable) SolveUptime(bootNumber int32, epoch NsEpoch) (NsUptime, error)
SolveUptime calculates propotional uptime from epoch and does validity check
type TimeVariableList ¶
type TimeVariableList []TimeVariable
func ParseTimeVariableList ¶
func ParseTimeVariableList(raw []byte, storeRTC bool) (TimeVariableList, error)
ParseTimeVariableList parses from raw byte array. Check length validity
func (*TimeVariableList) GetFirstsInBoot ¶
func (p *TimeVariableList) GetFirstsInBoot() TimeVariableList
GetFirstsInBoot picks first entries from each boot by index
func (*TimeVariableList) GetVariablesInBoot ¶
func (p *TimeVariableList) GetVariablesInBoot(boot int32) TimeVariableList
GetVariablesInBoot give all entries with specific boot number
func (TimeVariableList) Len ¶
func (e TimeVariableList) Len() int
Len number of TimeVariables in list
func (TimeVariableList) Less ¶
func (e TimeVariableList) Less(i, j int) bool
Less function for sorting
func (*TimeVariableList) SearchTimeVariable ¶
func (p *TimeVariableList) SearchTimeVariable(epoch NsEpoch) (TimeVariable, error)
SearchTimeVariable from list that is nearest to parameter epoch (at same boot)
func (*TimeVariableList) SolveBootNumber ¶
func (p *TimeVariableList) SolveBootNumber(epoch NsEpoch) (int32, error)
SolveBootNumber searches from list. Assumption is that array is sorted.. old at low indexes... newest at higher indexes
func (*TimeVariableList) SolveEpoch ¶
func (p *TimeVariableList) SolveEpoch(bootNumber int32, uptime NsUptime) (NsEpoch, error)
SolveEpoch picks TimeVariable entry at defined boot number just before or at uptime and uses that for solving epoch
func (TimeVariableList) String ¶
func (p TimeVariableList) String() string
String representation from TimeVariableList with newline at end
type UptimeChecker ¶
type UptimeChecker struct {
// contains filtered or unexported fields
}
func CreateUptimeChecker ¶
func CreateUptimeChecker() (UptimeChecker, error)
Creates uptime checker, reads uptime and sets creation time
func (*UptimeChecker) UptimeNano ¶
func (p *UptimeChecker) UptimeNano(tNow time.Time) (NsUptime, error)
UptimeNano resolves what is uptime on specific timestamp