Tue, 06 Feb 2018 20:16:59 +0000
Changed dreamtime calculation.
The monotonic clock (time.monotonic()) sometimes advances unreliably
in sleep, so isn't reliable for calculating sleeping time. We have to
use time.time(). But this may be changed by the user, so we only use
it to track sleep periods, and still use time.monotonic() to track
wake periods.
borgend/dreamtime.py | file | annotate | diff | comparison | revisions | |
borgend/ui.py | file | annotate | diff | comparison | revisions |
--- a/borgend/dreamtime.py Tue Feb 06 08:30:20 2018 +0000 +++ b/borgend/dreamtime.py Tue Feb 06 20:16:59 2018 +0000 @@ -215,10 +215,16 @@ class SleepHandler(Foundation.NSObject): """ Handle wake/sleep notifications """ + # We need to use the actual time.time() to monitor sleep, as + # time.monotonic() many not run during sleep. But time.time() + # may encounter adjustments, so we also use time.monotonic() to + # monitor wake periods. + def init(self): self.__sleeptime=None - self.__slept=0 - self.__epoch=time.monotonic() + self.__dreamtime_last_sleep=0 + self.__monotonic_last_wakeup=time.monotonic() + self.__slept=0 # Only used to store the statistic self.__lock=threading.Lock() self.__callbacks=weakref.WeakKeyDictionary() @@ -227,18 +233,21 @@ @protect_noreturn def handleSleepNotification_(self, aNotification): logger.info("System going to sleep") - now=time.monotonic() with self.__lock: - self.__sleeptime=now + self.__sleeptime=time.time() + now_m=time.monotonic() + self.__dreamtime_last_sleep=(self.__dreamtime_last_sleep+now_m + -self.__monotonic_last_wakeup) callbacks=self.__callbacks.copy() do_callbacks(callbacks, False) @protect_noreturn def handleWakeNotification_(self, aNotification): logger.info("System waking up from sleep") - now=time.monotonic() with self.__lock: if self.__sleeptime: + self.__monotonic_last_wakeup=time.monotonic() + now=time.time() slept=max(0, now-self.__sleeptime) logger.info("Slept %f seconds" % slept) self.__slept=self.__slept+slept @@ -248,7 +257,6 @@ # Return dreamtime def dreamtime_sleeping(self, snapshot=Snapshot()): - sleeping=False with self.__lock: # macOS "sleep" signals / status are complete bollocks: at least # when plugged in, the system is actually sometimes running all @@ -256,11 +264,13 @@ # Therefore, we need our timers to work in a sane manner when # we should be sleeping! if self.__sleeptime is not None: - now_monotonic=self.__sleeptime sleeping=True + now_dreamtime=self.__dreamtime_last_sleep else: - now_monotonic=snapshot.monotonic() - now_dreamtime=max(0, now_monotonic-self.__epoch-self.__slept) + sleeping=False + now=snapshot.monotonic() + now_dreamtime=(self.__dreamtime_last_sleep + +now-self.__monotonic_last_wakeup); return now_dreamtime, sleeping # Weirdo (Py)ObjC naming to stop it form choking up
--- a/borgend/ui.py Tue Feb 06 08:30:20 2018 +0000 +++ b/borgend/ui.py Tue Feb 06 20:16:59 2018 +0000 @@ -129,7 +129,7 @@ diff=datetime.timedelta(seconds=when-now) if twhen<tnow: - whenstr='overdue' + whenstr='overdue' + (' on %s' % twhen.isoformat()) elif twhen>tendtomorrow: # Display date if scheduled event is after tomorrow whenday=datetime.date.fromtimestamp(when)