sapling/eden/fs/inodes/InodeTimestamps.h
Chad Austin 7335196fed helper function for updating the time fields in struct stat
Summary: This gets rid of those pesky #ifdefs in FileInode.cpp and TreeInode.cpp.

Reviewed By: wez

Differential Revision: D7735914

fbshipit-source-id: d810461984e21f72670f43ca2d1b4f5aacbf376e
2018-04-24 13:44:10 -07:00

143 lines
3.2 KiB
C++

/*
* Copyright (c) 2018-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/
#pragma once
#include "eden/fs/utils/TimeUtil.h"
#include <stdint.h>
#include <time.h>
struct fuse_setattr_in;
struct stat;
namespace facebook {
namespace eden {
class Clock;
/**
* 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.
*/
explicit EdenTimestamp(uint64_t nsec) : nsec_(nsec) {}
/**
* Converts a timespec to an EdenTimestamp.
*
* If the timespec is out of range, it is clamped.
*/
explicit EdenTimestamp(timespec ts, Clamp = clamp);
/**
* 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;
EdenTimestamp& operator=(timespec ts) {
return *this = EdenTimestamp{ts};
}
bool operator<(EdenTimestamp ts) const {
return nsec_ < ts.nsec_;
}
bool operator<(timespec ts) const {
return toTimespec() < ts;
}
/**
* Returns a timespec representing duration since the unix epoch.
*/
timespec toTimespec() const;
/**
* Returns the raw representation -- should be for testing only. :)
*/
uint64_t asRawRepresentation() const {
return nsec_;
}
private:
uint64_t nsec_{0};
};
/**
* Structure for wrapping atime,ctime,mtime
*/
struct InodeTimestamps {
EdenTimestamp atime{};
EdenTimestamp mtime{};
EdenTimestamp ctime{};
/**
* Initializes all timestamps to zero.
*/
InodeTimestamps() {}
/**
* Initializes all timestamps from the same value.
*/
explicit InodeTimestamps(const timespec& ts)
: atime(ts), mtime(ts), ctime(ts) {}
/**
* Assigns the specified ts to atime, mtime, and ctime.
*/
void setAll(const timespec& ts) {
atime = ts;
mtime = ts;
ctime = ts;
}
/**
* Helper that assigns all three timestamps from the flags and parameters in
* a fuse_setattr_in struct.
*
* Always sets ctime to the current time as given by the clock.
*/
void setattrTimes(const Clock& clock, const fuse_setattr_in& attr);
/**
* Updates st_atime, st_mtime, and st_ctime of the given stat struct.
*/
void applyToStat(struct stat& st) const;
};
} // namespace eden
} // namespace facebook