2018-02-01 23:21:03 +03:00
|
|
|
/*
|
2019-06-20 02:58:25 +03:00
|
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
2018-02-01 23:21:03 +03:00
|
|
|
*
|
2019-06-20 02:58:25 +03:00
|
|
|
* This software may be used and distributed according to the terms of the
|
|
|
|
* GNU General Public License version 2.
|
2018-02-01 23:21:03 +03:00
|
|
|
*/
|
2019-10-11 15:26:59 +03:00
|
|
|
|
2018-02-01 23:21:03 +03:00
|
|
|
#pragma once
|
|
|
|
|
2018-02-16 03:00:42 +03:00
|
|
|
#include "eden/fs/utils/TimeUtil.h"
|
|
|
|
|
|
|
|
#include <stdint.h>
|
2018-02-01 23:21:03 +03:00
|
|
|
#include <time.h>
|
|
|
|
|
2018-04-24 23:20:52 +03:00
|
|
|
struct stat;
|
2018-02-01 23:21:03 +03:00
|
|
|
|
|
|
|
namespace facebook {
|
|
|
|
namespace eden {
|
|
|
|
|
|
|
|
class Clock;
|
2021-03-05 22:08:54 +03:00
|
|
|
struct DesiredMetadata;
|
2018-02-01 23:21:03 +03:00
|
|
|
|
2018-02-16 03:00:42 +03:00
|
|
|
/**
|
|
|
|
* For space efficiency, store timestamps in a single 64-bit value as
|
|
|
|
* nanoseconds from 1901-12-13 (-0x80000000 seconds before unix epoch) through
|
|
|
|
* 2446. This range is similar to ext4's timestamp range, though slightly
|
|
|
|
* larger.
|
|
|
|
*
|
|
|
|
* https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout#Inode_Timestamps
|
|
|
|
*/
|
|
|
|
class EdenTimestamp {
|
|
|
|
public:
|
|
|
|
constexpr static struct Clamp {
|
|
|
|
} clamp{};
|
|
|
|
constexpr static struct ThrowIfOutOfRange {
|
|
|
|
} throwIfOutOfRange{};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Default construction produces a timestamp at EdenTimestamp's earliest
|
|
|
|
* representable value.
|
|
|
|
*/
|
|
|
|
EdenTimestamp() = default;
|
|
|
|
|
|
|
|
EdenTimestamp(const EdenTimestamp&) = default;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructs an EdenTimestamp given a raw uint64_t in nanoseconds since
|
|
|
|
* the earliest representable ext4 timestamp.
|
|
|
|
*/
|
2018-05-10 02:20:44 +03:00
|
|
|
explicit EdenTimestamp(uint64_t nsec) noexcept : nsec_(nsec) {}
|
2018-02-16 03:00:42 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Converts a timespec to an EdenTimestamp.
|
|
|
|
*
|
|
|
|
* If the timespec is out of range, it is clamped.
|
|
|
|
*/
|
2018-05-10 02:20:44 +03:00
|
|
|
explicit EdenTimestamp(timespec ts, Clamp = clamp) noexcept;
|
2018-02-16 03:00:42 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Converts a timespec to an EdenTimestamp.
|
|
|
|
*
|
|
|
|
* If the timespec is out of range, std::overflow_error or
|
|
|
|
* std::underflow_error is thrown.
|
|
|
|
*/
|
|
|
|
EdenTimestamp(timespec ts, ThrowIfOutOfRange);
|
|
|
|
|
|
|
|
EdenTimestamp& operator=(const EdenTimestamp&) = default;
|
|
|
|
|
2018-05-10 02:20:44 +03:00
|
|
|
EdenTimestamp& operator=(timespec ts) noexcept {
|
2018-02-16 03:00:42 +03:00
|
|
|
return *this = EdenTimestamp{ts};
|
|
|
|
}
|
|
|
|
|
2018-06-01 21:16:48 +03:00
|
|
|
bool operator==(EdenTimestamp ts) const {
|
|
|
|
return nsec_ == ts.nsec_;
|
2018-02-16 03:00:42 +03:00
|
|
|
}
|
|
|
|
|
2018-06-01 21:16:48 +03:00
|
|
|
bool operator<(EdenTimestamp ts) const {
|
|
|
|
return nsec_ < ts.nsec_;
|
2018-02-16 03:00:42 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns a timespec representing duration since the unix epoch.
|
|
|
|
*/
|
2018-05-10 02:20:44 +03:00
|
|
|
timespec toTimespec() const noexcept;
|
2018-02-16 03:00:42 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the raw representation -- should be for testing only. :)
|
|
|
|
*/
|
2018-05-10 02:20:44 +03:00
|
|
|
uint64_t asRawRepresentation() const noexcept {
|
2018-02-16 03:00:42 +03:00
|
|
|
return nsec_;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
uint64_t nsec_{0};
|
|
|
|
};
|
|
|
|
|
2018-06-01 21:16:48 +03:00
|
|
|
inline bool operator!=(EdenTimestamp lhs, EdenTimestamp rhs) {
|
|
|
|
return !(lhs == rhs);
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool operator==(EdenTimestamp lhs, timespec rhs) {
|
|
|
|
// Widen before comparing.
|
|
|
|
return lhs.toTimespec() == rhs;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool operator==(timespec lhs, EdenTimestamp rhs) {
|
|
|
|
// Widen before comparing.
|
|
|
|
return lhs == rhs.toTimespec();
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool operator<(EdenTimestamp lhs, timespec rhs) {
|
|
|
|
// Widen before comparing.
|
|
|
|
return lhs.toTimespec() < rhs;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool operator<(timespec lhs, EdenTimestamp rhs) {
|
|
|
|
// Widen before comparing.
|
|
|
|
return lhs < rhs.toTimespec();
|
|
|
|
}
|
|
|
|
|
2018-02-01 23:21:03 +03:00
|
|
|
/**
|
|
|
|
* Structure for wrapping atime,ctime,mtime
|
|
|
|
*/
|
|
|
|
struct InodeTimestamps {
|
2018-02-16 03:00:44 +03:00
|
|
|
EdenTimestamp atime{};
|
|
|
|
EdenTimestamp mtime{};
|
|
|
|
EdenTimestamp ctime{};
|
2018-02-01 23:21:03 +03:00
|
|
|
|
2018-02-02 03:07:02 +03:00
|
|
|
/**
|
|
|
|
* Initializes all timestamps to zero.
|
|
|
|
*/
|
2018-05-10 02:20:44 +03:00
|
|
|
InodeTimestamps() = default;
|
2018-02-02 03:07:02 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Initializes all timestamps from the same value.
|
|
|
|
*/
|
2021-04-20 00:37:23 +03:00
|
|
|
explicit InodeTimestamps(const EdenTimestamp time) noexcept
|
|
|
|
: atime{time}, mtime{time}, ctime{time} {}
|
2018-02-02 03:07:02 +03:00
|
|
|
|
2018-02-01 23:21:03 +03:00
|
|
|
/**
|
|
|
|
* Assigns the specified ts to atime, mtime, and ctime.
|
|
|
|
*/
|
2018-05-10 02:20:44 +03:00
|
|
|
void setAll(const timespec& ts) noexcept {
|
2018-02-01 23:21:03 +03:00
|
|
|
atime = ts;
|
|
|
|
mtime = ts;
|
|
|
|
ctime = ts;
|
|
|
|
}
|
|
|
|
|
2020-04-02 00:51:06 +03:00
|
|
|
#ifndef _WIN32
|
2018-02-01 23:21:03 +03:00
|
|
|
/**
|
|
|
|
* Helper that assigns all three timestamps from the flags and parameters in
|
2021-03-05 22:08:54 +03:00
|
|
|
* a DesiredMetadata struct.
|
2018-02-01 23:21:03 +03:00
|
|
|
*
|
|
|
|
* Always sets ctime to the current time as given by the clock.
|
|
|
|
*/
|
2021-03-05 22:08:54 +03:00
|
|
|
void setattrTimes(const Clock& clock, const DesiredMetadata& attr);
|
2018-04-24 23:20:52 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Updates st_atime, st_mtime, and st_ctime of the given stat struct.
|
|
|
|
*/
|
|
|
|
void applyToStat(struct stat& st) const;
|
2020-04-02 00:51:06 +03:00
|
|
|
#endif
|
2018-02-01 23:21:03 +03:00
|
|
|
};
|
|
|
|
|
2018-05-10 02:20:44 +03:00
|
|
|
static_assert(noexcept(EdenTimestamp{}), "");
|
|
|
|
static_assert(noexcept(EdenTimestamp{timespec{}}), "");
|
|
|
|
static_assert(noexcept(EdenTimestamp{uint64_t{}}), "");
|
|
|
|
|
|
|
|
static_assert(noexcept(InodeTimestamps{}), "");
|
|
|
|
|
2018-02-01 23:21:03 +03:00
|
|
|
} // namespace eden
|
|
|
|
} // namespace facebook
|