From: Wolfgang Bumiller <w.bumiller@proxmox.com>
To: pbs-devel@lists.proxmox.com
Subject: [pbs-devel] [PATCH pxar v2 2/6] introduce StatxTimestamp helper type
Date: Tue, 28 Jul 2020 16:05:22 +0200 [thread overview]
Message-ID: <20200728140522.i3unopokwr35ug57@olga.proxmox.com> (raw)
In-Reply-To: <20200728103321.16843-4-w.bumiller@proxmox.com>
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
---
changes to v1:
Add testcase with nanos=0
Fix nanos=0 case in `from_duration_before_epoch`.
(added comment about why `to_duration` doesn't need special handling,
that is because std::time::Duration already does that)
src/format/mod.rs | 115 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 115 insertions(+)
diff --git a/src/format/mod.rs b/src/format/mod.rs
index 0f9db79..1a38157 100644
--- a/src/format/mod.rs
+++ b/src/format/mod.rs
@@ -43,6 +43,7 @@ use std::io;
use std::mem::size_of;
use std::os::unix::ffi::OsStrExt;
use std::path::Path;
+use std::time::{Duration, SystemTime};
use endian_trait::Endian;
use siphasher::sip::SipHasher24;
@@ -194,6 +195,120 @@ impl Display for Header {
}
}
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum SignedDuration {
+ Positive(Duration),
+ Negative(Duration),
+}
+
+#[derive(Clone, Debug, Default, Endian, Eq, PartialEq)]
+#[repr(C)]
+pub struct StatxTimestamp {
+ /// Seconds since the epoch (unix time).
+ pub secs: i64,
+
+ /// Nanoseconds since this struct's `secs`.
+ pub nanos: u32,
+}
+
+impl From<SystemTime> for StatxTimestamp {
+ fn from(time: SystemTime) -> Self {
+ match time.duration_since(SystemTime::UNIX_EPOCH) {
+ Ok(positive) => Self::from_duration_since_epoch(positive),
+ Err(negative) => Self::from_duration_before_epoch(negative.duration()),
+ }
+ }
+}
+
+impl StatxTimestamp {
+ /// `const` version of `Default`
+ pub const fn zero() -> Self {
+ Self { secs: 0, nanos: 0 }
+ }
+
+ /// Turn a positive duration relative to the unix epoch into a time stamp.
+ pub fn from_duration_since_epoch(duration: Duration) -> Self {
+ Self {
+ secs: duration.as_secs() as i64,
+ nanos: duration.subsec_nanos(),
+ }
+ }
+
+ /// Turn a *negative* duration from relative to the unix epoch into a time stamp.
+ pub fn from_duration_before_epoch(duration: Duration) -> Self {
+ match duration.subsec_nanos() {
+ 0 => Self {
+ secs: -(duration.as_secs() as i64),
+ nanos: 0,
+ },
+ nanos => Self {
+ secs: -(duration.as_secs() as i64) - 1,
+ nanos: 1_000_000_000 - nanos,
+ },
+ }
+ }
+
+ /// Get the duration since the epoch. an `Ok` value is a positive duration, an `Err` value is a
+ /// negative duration.
+ pub fn to_duration(&self) -> SignedDuration {
+ if self.secs >= 0 {
+ SignedDuration::Positive(Duration::new(self.secs as u64, self.nanos))
+ } else {
+ // this handles the nanos=0 case as `Duration::new()` performs the carry-over.
+ SignedDuration::Negative(Duration::new(
+ -(self.secs + 1) as u64,
+ 1_000_000_000 - self.nanos,
+ ))
+ }
+ }
+
+ /// Get a `std::time::SystemTime` from this time stamp.
+ pub fn system_time(&self) -> SystemTime {
+ match self.to_duration() {
+ SignedDuration::Positive(positive) => SystemTime::UNIX_EPOCH + positive,
+ SignedDuration::Negative(negative) => SystemTime::UNIX_EPOCH - negative,
+ }
+ }
+}
+
+#[test]
+fn test_statx_timestamp() {
+ const MAY_1_2015_1530: i64 = 1430487000;
+ let system_time = SystemTime::UNIX_EPOCH + Duration::new(MAY_1_2015_1530 as u64, 1_000_000);
+ let tx = StatxTimestamp::from(system_time);
+ assert_eq!(
+ tx,
+ StatxTimestamp {
+ secs: MAY_1_2015_1530,
+ nanos: 1_000_000,
+ }
+ );
+ assert_eq!(tx.system_time(), system_time);
+
+ const MAY_1_1960_1530: i64 = -305112600;
+ let system_time = SystemTime::UNIX_EPOCH - Duration::new(-MAY_1_1960_1530 as u64, 1_000_000);
+ let tx = StatxTimestamp::from(system_time);
+ assert_eq!(
+ tx,
+ StatxTimestamp {
+ secs: MAY_1_1960_1530 - 1,
+ nanos: 999_000_000,
+ }
+ );
+ assert_eq!(tx.system_time(), system_time);
+
+ let system_time = SystemTime::UNIX_EPOCH - Duration::new(-MAY_1_1960_1530 as u64, 0);
+ let tx = StatxTimestamp::from(system_time);
+ assert_eq!(
+ tx,
+ StatxTimestamp {
+ secs: MAY_1_1960_1530,
+ nanos: 0,
+ }
+ );
+ assert_eq!(tx.system_time(), system_time);
+}
+
#[derive(Clone, Debug, Default, Endian)]
#[cfg_attr(feature = "test-harness", derive(Eq, PartialEq))]
#[repr(C)]
--
2.20.1
next prev parent reply other threads:[~2020-07-28 14:05 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-07-28 10:33 [pbs-devel] [PATCH pxar/backup 0/6] bump timestamps to 96 bit Wolfgang Bumiller
2020-07-28 10:33 ` [pbs-devel] [PATCH pxar 1/6] add format description to format module Wolfgang Bumiller
2020-07-28 10:33 ` [pbs-devel] [PATCH backup] update to pxar 0.3 to support negative timestamps Wolfgang Bumiller
2020-07-29 6:32 ` [pbs-devel] applied: " Dietmar Maurer
2020-07-28 10:33 ` [pbs-devel] [PATCH pxar 2/6] introduce StatxTimestamp helper type Wolfgang Bumiller
2020-07-28 14:05 ` Wolfgang Bumiller [this message]
2020-07-28 10:33 ` [pbs-devel] [PATCH pxar 3/6] update mk-format-hashes for a new ENTRY Wolfgang Bumiller
2020-07-28 10:33 ` [pbs-devel] [PATCH pxar 4/6] implement Entry v2 Wolfgang Bumiller
2020-07-28 10:33 ` [pbs-devel] [PATCH pxar 5/6] add entry v1 compatiblity test Wolfgang Bumiller
2020-07-28 10:33 ` [pbs-devel] [PATCH pxar 6/6] bump version to 0.3.0-1 Wolfgang Bumiller
2020-07-29 6:14 ` [pbs-devel] applied: [PATCH pxar/backup 0/6] bump timestamps to 96 bit Dietmar Maurer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200728140522.i3unopokwr35ug57@olga.proxmox.com \
--to=w.bumiller@proxmox.com \
--cc=pbs-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.