sapling/eden/fs/fuse/InodeNumber.h
Chad Austin 1c84f3f115 split InodeNumber into its own file
Summary:
It's common for code to use InodeNumber without needing to include the
main FUSE headers or vice versa. Split them into two separate headers.

Reviewed By: strager

Differential Revision: D13979868

fbshipit-source-id: c5eeb6a3697bb538729a403434dc4f0f7408cda0
2019-02-08 16:21:35 -08:00

149 lines
4.0 KiB
C++

/*
* Copyright (c) 2017-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 <assert.h>
#include <folly/Format.h>
#include <glog/logging.h>
#include <stdint.h>
namespace facebook {
namespace eden {
/**
* Represents ino_t behind a slightly safer API. In general, it is a bug if
* Eden produces inode numbers with the value 0, so this class makes it harder
* to do that on accident.
*/
struct InodeNumber {
/// Default-initializes the inode number to 0.
constexpr InodeNumber() noexcept = default;
/**
* Initializes with a given nonzero number. Will assert in debug builds if
* initialized to zero.
*/
constexpr explicit InodeNumber(uint64_t ino) noexcept : rawValue_{ino} {
// This is intentionally an assert() rather than DCHECK_NE() since
// DCHECK_NE is not allowed in constexpr methods.
assert(0 != rawValue_);
}
/**
* Thrift does not support unsigned numbers, so it's common to instantiate
* InodeNumber from int64_t.
*/
static InodeNumber fromThrift(int64_t ino) {
return InodeNumber{static_cast<uint64_t>(ino)};
}
/**
* Returns a nonzero inode number. Asserts in debug builds if zero.
*
* Use this accessor when handing inode numbers to FUSE.
*/
uint64_t get() const {
DCHECK_NE(0, rawValue_);
return rawValue_;
}
/**
* Returns true if initialized with a nonzero inode number.
*/
constexpr bool hasValue() const {
return rawValue_ != 0;
}
/**
* Returns true if underlying value is zero.
*/
constexpr bool empty() const {
return rawValue_ == 0;
}
/**
* Returns the underlying value whether or not it's zero. Use this accessor
* when debugging or in tests.
*/
constexpr uint64_t getRawValue() const {
return rawValue_;
}
private:
uint64_t rawValue_{0};
};
inline bool operator==(InodeNumber lhs, InodeNumber rhs) {
return lhs.getRawValue() == rhs.getRawValue();
}
inline bool operator!=(InodeNumber lhs, InodeNumber rhs) {
return lhs.getRawValue() != rhs.getRawValue();
}
inline bool operator<(InodeNumber lhs, InodeNumber rhs) {
return lhs.getRawValue() < rhs.getRawValue();
}
inline bool operator<=(InodeNumber lhs, InodeNumber rhs) {
return lhs.getRawValue() <= rhs.getRawValue();
}
inline bool operator>(InodeNumber lhs, InodeNumber rhs) {
return lhs.getRawValue() > rhs.getRawValue();
}
inline bool operator>=(InodeNumber lhs, InodeNumber rhs) {
return lhs.getRawValue() >= rhs.getRawValue();
}
std::ostream& operator<<(std::ostream& os, InodeNumber ino);
// Define toAppend() so folly::to<string>(ino) will work.
void toAppend(InodeNumber ino, std::string* result);
// Define toAppend() so folly::to<fbstring>(ino) will work.
void toAppend(InodeNumber ino, folly::fbstring* result);
constexpr InodeNumber operator""_ino(unsigned long long ino) {
return InodeNumber{ino};
}
/// The inode number of the mount's root directory.
constexpr InodeNumber kRootNodeId = 1_ino;
} // namespace eden
} // namespace facebook
namespace std {
template <>
struct hash<facebook::eden::InodeNumber> {
size_t operator()(facebook::eden::InodeNumber n) const {
// TODO: It may be worth using a different hash function. The default
// std::hash for integers is the identity function. But since we allocate
// inode numbers monotonically, this should be okay.
return std::hash<uint64_t>{}(n.getRawValue());
}
};
} // namespace std
namespace folly {
template <>
class FormatValue<facebook::eden::InodeNumber> {
public:
explicit FormatValue(facebook::eden::InodeNumber ino) : ino_(ino) {}
template <class FormatCallback>
void format(FormatArg& arg, FormatCallback& cb) const {
FormatValue<uint64_t>{ino_.getRawValue()}.format(arg, cb);
}
private:
const facebook::eden::InodeNumber ino_;
};
} // namespace folly