mirror of
https://github.com/facebook/sapling.git
synced 2024-09-11 10:36:52 +03:00
Simplify Journal API for Callers
Summary: Making addDelta private and giving users a more user-friendly way of appending entries to the journal. Reviewed By: chadaustin, strager Differential Revision: D15868089 fbshipit-source-id: 00c8a3066f0e4483e3c792651ade5f6a7ea05eed
This commit is contained in:
parent
73e2c2a997
commit
26a6e91e05
@ -90,7 +90,7 @@ const PathComponentPiece kDotEdenSymlinkName{"this-dir"_pc};
|
||||
class EdenMount::JournalDiffCallback : public InodeDiffCallback {
|
||||
public:
|
||||
explicit JournalDiffCallback()
|
||||
: data_{folly::in_place, make_unique<JournalDelta>()} {}
|
||||
: data_{folly::in_place, std::unordered_set<RelativePath>()} {}
|
||||
|
||||
void ignoredFile(RelativePathPiece) override {}
|
||||
|
||||
@ -99,13 +99,13 @@ class EdenMount::JournalDiffCallback : public InodeDiffCallback {
|
||||
void removedFile(
|
||||
RelativePathPiece path,
|
||||
const TreeEntry& /* sourceControlEntry */) override {
|
||||
data_.wlock()->journalDelta->uncleanPaths.insert(path.copy());
|
||||
data_.wlock()->uncleanPaths.insert(path.copy());
|
||||
}
|
||||
|
||||
void modifiedFile(
|
||||
RelativePathPiece path,
|
||||
const TreeEntry& /* sourceControlEntry */) override {
|
||||
data_.wlock()->journalDelta->uncleanPaths.insert(path.copy());
|
||||
data_.wlock()->uncleanPaths.insert(path.copy());
|
||||
}
|
||||
|
||||
void diffError(RelativePathPiece path, const folly::exception_wrapper& ew)
|
||||
@ -133,21 +133,21 @@ class EdenMount::JournalDiffCallback : public InodeDiffCallback {
|
||||
.ensure([diffContext = std::move(diffContext)]() {});
|
||||
}
|
||||
|
||||
/** moves the JournalDelta information out of this diff callback instance,
|
||||
/** moves the Unclean Path information out of this diff callback instance,
|
||||
* rendering it invalid */
|
||||
std::unique_ptr<JournalDelta> stealJournalDelta() {
|
||||
std::unique_ptr<JournalDelta> result;
|
||||
std::swap(result, data_.wlock()->journalDelta);
|
||||
std::unordered_set<RelativePath> stealUncleanPaths() {
|
||||
std::unordered_set<RelativePath> result;
|
||||
std::swap(result, data_.wlock()->uncleanPaths);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
struct Data {
|
||||
explicit Data(unique_ptr<JournalDelta>&& journalDelta)
|
||||
: journalDelta(std::move(journalDelta)) {}
|
||||
explicit Data(std::unordered_set<RelativePath>&& unclean)
|
||||
: uncleanPaths(std::move(unclean)) {}
|
||||
|
||||
unique_ptr<JournalDelta> journalDelta;
|
||||
std::unordered_set<RelativePath> uncleanPaths;
|
||||
};
|
||||
folly::Synchronized<Data> data_;
|
||||
};
|
||||
@ -218,9 +218,7 @@ folly::Future<folly::Unit> EdenMount::initialize(
|
||||
// Record the transition from no snapshot to the current snapshot in
|
||||
// the journal. This also sets things up so that we can carry the
|
||||
// snapshot id forward through subsequent journal entries.
|
||||
auto delta = std::make_unique<JournalDelta>();
|
||||
delta->toHash = parents.parent1();
|
||||
journal_.addDelta(std::move(delta));
|
||||
journal_.recordHashUpdate(parents.parent1());
|
||||
|
||||
// Initialize the overlay.
|
||||
// This must be performed before we do any operations that may allocate
|
||||
@ -734,10 +732,9 @@ folly::Future<std::vector<CheckoutConflict>> EdenMount::checkout(
|
||||
// either been unclean before it started, or different between the
|
||||
// two trees. Therefore the JournalDelta already includes information
|
||||
// that these files changed.
|
||||
auto journalDelta = journalDiffCallback->stealJournalDelta();
|
||||
journalDelta->fromHash = oldParents.parent1();
|
||||
journalDelta->toHash = snapshotHash;
|
||||
journal_.addDelta(std::move(journalDelta));
|
||||
auto uncleanPaths = journalDiffCallback->stealUncleanPaths();
|
||||
journal_.recordUncleanPaths(
|
||||
oldParents.parent1(), snapshotHash, std::move(uncleanPaths));
|
||||
|
||||
return std::move(conflicts);
|
||||
});
|
||||
@ -820,10 +817,7 @@ void EdenMount::resetParents(const ParentCommits& parents) {
|
||||
config_->setParentCommits(parents);
|
||||
parentsLock->parents.setParents(parents);
|
||||
|
||||
auto journalDelta = make_unique<JournalDelta>();
|
||||
journalDelta->fromHash = oldParents.parent1();
|
||||
journalDelta->toHash = parents.parent1();
|
||||
journal_.addDelta(std::move(journalDelta));
|
||||
journal_.recordHashUpdate(oldParents.parent1(), parents.parent1());
|
||||
}
|
||||
|
||||
struct timespec EdenMount::getLastCheckoutTime() const {
|
||||
|
@ -759,8 +759,7 @@ size_t FileInode::writeImpl(
|
||||
|
||||
auto myname = getPath();
|
||||
if (myname.has_value()) {
|
||||
getMount()->getJournal().addDelta(std::make_unique<JournalDelta>(
|
||||
std::move(myname.value()), JournalDelta::CHANGED));
|
||||
getMount()->getJournal().recordChanged(std::move(myname.value()));
|
||||
}
|
||||
|
||||
return xfer;
|
||||
|
@ -380,8 +380,7 @@ const Clock& InodeBase::getClock() const {
|
||||
void InodeBase::updateJournal() {
|
||||
auto path = getPath();
|
||||
if (path.has_value()) {
|
||||
getMount()->getJournal().addDelta(std::make_unique<JournalDelta>(
|
||||
std::move(path.value()), JournalDelta::CHANGED));
|
||||
getMount()->getJournal().recordChanged(std::move(path.value()));
|
||||
}
|
||||
}
|
||||
} // namespace eden
|
||||
|
@ -919,8 +919,7 @@ FileInodePtr TreeInode::createImpl(
|
||||
invalidateFuseEntryCacheIfRequired(name);
|
||||
invalidateFuseInodeCacheIfRequired();
|
||||
|
||||
getMount()->getJournal().addDelta(
|
||||
std::make_unique<JournalDelta>(targetName, JournalDelta::CREATED));
|
||||
getMount()->getJournal().recordCreated(targetName);
|
||||
|
||||
return inode;
|
||||
}
|
||||
@ -1074,8 +1073,7 @@ TreeInodePtr TreeInode::mkdir(PathComponentPiece name, mode_t mode) {
|
||||
|
||||
invalidateFuseEntryCacheIfRequired(name);
|
||||
invalidateFuseInodeCacheIfRequired();
|
||||
getMount()->getJournal().addDelta(
|
||||
std::make_unique<JournalDelta>(targetName, JournalDelta::CREATED));
|
||||
getMount()->getJournal().recordCreated(targetName);
|
||||
|
||||
return newChild;
|
||||
}
|
||||
@ -1145,8 +1143,7 @@ folly::Future<folly::Unit> TreeInode::removeImpl(
|
||||
if (errnoValue == 0) {
|
||||
// We successfully removed the child.
|
||||
// Record the change in the journal.
|
||||
getMount()->getJournal().addDelta(
|
||||
std::make_unique<JournalDelta>(targetName, JournalDelta::REMOVED));
|
||||
getMount()->getJournal().recordRemoved(targetName);
|
||||
|
||||
return folly::unit;
|
||||
}
|
||||
@ -1596,15 +1593,11 @@ Future<Unit> TreeInode::doRename(
|
||||
auto destPath = destParent->getPath();
|
||||
if (srcPath.has_value() && destPath.has_value()) {
|
||||
if (destChildExists) {
|
||||
getMount()->getJournal().addDelta(std::make_unique<JournalDelta>(
|
||||
srcPath.value() + srcName,
|
||||
destPath.value() + destName,
|
||||
JournalDelta::REPLACE));
|
||||
getMount()->getJournal().recordReplaced(
|
||||
srcPath.value() + srcName, destPath.value() + destName);
|
||||
} else {
|
||||
getMount()->getJournal().addDelta(std::make_unique<JournalDelta>(
|
||||
srcPath.value() + srcName,
|
||||
destPath.value() + destName,
|
||||
JournalDelta::RENAME));
|
||||
getMount()->getJournal().recordRenamed(
|
||||
srcPath.value() + srcName, destPath.value() + destName);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,56 @@
|
||||
namespace facebook {
|
||||
namespace eden {
|
||||
|
||||
void Journal::recordCreated(RelativePathPiece fileName) {
|
||||
addDelta(std::make_unique<JournalDelta>(fileName, JournalDelta::CREATED));
|
||||
}
|
||||
|
||||
void Journal::recordRemoved(RelativePathPiece fileName) {
|
||||
addDelta(std::make_unique<JournalDelta>(fileName, JournalDelta::REMOVED));
|
||||
}
|
||||
|
||||
void Journal::recordChanged(RelativePathPiece fileName) {
|
||||
addDelta(std::make_unique<JournalDelta>(fileName, JournalDelta::CHANGED));
|
||||
}
|
||||
|
||||
void Journal::recordRenamed(
|
||||
RelativePathPiece oldName,
|
||||
RelativePathPiece newName) {
|
||||
addDelta(
|
||||
std::make_unique<JournalDelta>(oldName, newName, JournalDelta::RENAMED));
|
||||
}
|
||||
|
||||
void Journal::recordReplaced(
|
||||
RelativePathPiece oldName,
|
||||
RelativePathPiece newName) {
|
||||
addDelta(
|
||||
std::make_unique<JournalDelta>(oldName, newName, JournalDelta::REPLACED));
|
||||
}
|
||||
|
||||
void Journal::recordHashUpdate(Hash toHash) {
|
||||
auto delta = std::make_unique<JournalDelta>();
|
||||
delta->toHash = toHash;
|
||||
addDelta(std::move(delta));
|
||||
}
|
||||
|
||||
void Journal::recordHashUpdate(Hash fromHash, Hash toHash) {
|
||||
auto delta = std::make_unique<JournalDelta>();
|
||||
delta->fromHash = fromHash;
|
||||
delta->toHash = toHash;
|
||||
addDelta(std::move(delta));
|
||||
}
|
||||
|
||||
void Journal::recordUncleanPaths(
|
||||
Hash fromHash,
|
||||
Hash toHash,
|
||||
std::unordered_set<RelativePath>&& uncleanPaths) {
|
||||
auto delta = std::make_unique<JournalDelta>();
|
||||
delta->fromHash = fromHash;
|
||||
delta->toHash = toHash;
|
||||
delta->uncleanPaths = std::move(uncleanPaths);
|
||||
addDelta(std::move(delta));
|
||||
}
|
||||
|
||||
void Journal::addDelta(std::unique_ptr<JournalDelta>&& delta) {
|
||||
{
|
||||
auto deltaState = deltaState_.wlock();
|
||||
|
@ -57,10 +57,39 @@ class Journal {
|
||||
using SubscriberId = uint64_t;
|
||||
using SubscriberCallback = std::function<void()>;
|
||||
|
||||
/** Add a delta to the journal
|
||||
* The delta will have a new sequence number and timestamp
|
||||
* applied. */
|
||||
void addDelta(std::unique_ptr<JournalDelta>&& delta);
|
||||
void recordCreated(RelativePathPiece fileName);
|
||||
void recordRemoved(RelativePathPiece fileName);
|
||||
void recordChanged(RelativePathPiece fileName);
|
||||
|
||||
/**
|
||||
* "Renamed" means that that newName was created as a result of the mv(1).
|
||||
*/
|
||||
void recordRenamed(RelativePathPiece oldName, RelativePathPiece newName);
|
||||
|
||||
/**
|
||||
* "Replaced" means that that newName was overwritten by oldName as a result
|
||||
* of the mv(1).
|
||||
*/
|
||||
void recordReplaced(RelativePathPiece oldName, RelativePathPiece newName);
|
||||
|
||||
/**
|
||||
* Creates a journal delta that updates the hash to this new hash
|
||||
*/
|
||||
void recordHashUpdate(Hash toHash);
|
||||
|
||||
/**
|
||||
* Creates a journal delta that updates the hash from fromHash to toHash
|
||||
*/
|
||||
void recordHashUpdate(Hash fromHash, Hash toHash);
|
||||
|
||||
/**
|
||||
* Creates a journal delta that updates the hash from fromHash to toHash and
|
||||
* also sets uncleanPaths
|
||||
*/
|
||||
void recordUncleanPaths(
|
||||
Hash fromHash,
|
||||
Hash toHash,
|
||||
std::unordered_set<RelativePath>&& uncleanPaths);
|
||||
|
||||
/** Get a shared, immutable reference to the tip of the journal.
|
||||
* May return nullptr if there have been no changes */
|
||||
@ -88,6 +117,12 @@ class Journal {
|
||||
std::optional<JournalStats> getStats();
|
||||
|
||||
private:
|
||||
/** Add a delta to the journal.
|
||||
* The delta will have a new sequence number and timestamp
|
||||
* applied.
|
||||
*/
|
||||
void addDelta(std::unique_ptr<JournalDelta>&& delta);
|
||||
|
||||
struct DeltaState {
|
||||
/** The sequence number that we'll use for the next entry
|
||||
* that we link into the chain */
|
||||
|
@ -50,8 +50,8 @@ class JournalDelta {
|
||||
enum Created { CREATED };
|
||||
enum Removed { REMOVED };
|
||||
enum Changed { CHANGED };
|
||||
enum Renamed { RENAME };
|
||||
enum Replaced { REPLACE };
|
||||
enum Renamed { RENAMED };
|
||||
enum Replaced { REPLACED };
|
||||
JournalDelta() = default;
|
||||
JournalDelta(JournalDelta&&) = delete;
|
||||
JournalDelta& operator=(JournalDelta&&) = delete;
|
||||
|
@ -18,9 +18,7 @@ TEST(Journal, merges_chained_deltas) {
|
||||
Journal journal;
|
||||
|
||||
// Make an initial entry.
|
||||
auto delta =
|
||||
std::make_unique<JournalDelta>("foo/bar"_relpath, JournalDelta::CHANGED);
|
||||
journal.addDelta(std::move(delta));
|
||||
journal.recordChanged("foo/bar"_relpath);
|
||||
|
||||
// Sanity check that the latest information matches.
|
||||
auto latest = journal.getLatest();
|
||||
@ -29,8 +27,7 @@ TEST(Journal, merges_chained_deltas) {
|
||||
EXPECT_EQ(nullptr, latest->previous);
|
||||
|
||||
// Add a second entry.
|
||||
delta = std::make_unique<JournalDelta>("baz"_relpath, JournalDelta::CHANGED);
|
||||
journal.addDelta(std::move(delta));
|
||||
journal.recordChanged("baz"_relpath);
|
||||
|
||||
// Sanity check that the latest information matches.
|
||||
latest = journal.getLatest();
|
||||
@ -77,17 +74,11 @@ TEST(Journal, mergeRemoveCreateUpdate) {
|
||||
Journal journal;
|
||||
|
||||
// Remove test.txt
|
||||
auto delta =
|
||||
std::make_unique<JournalDelta>("test.txt"_relpath, JournalDelta::REMOVED);
|
||||
journal.addDelta(std::move(delta));
|
||||
journal.recordRemoved("test.txt"_relpath);
|
||||
// Create test.txt
|
||||
delta =
|
||||
std::make_unique<JournalDelta>("test.txt"_relpath, JournalDelta::CREATED);
|
||||
journal.addDelta(std::move(delta));
|
||||
journal.recordCreated("test.txt"_relpath);
|
||||
// Modify test.txt
|
||||
delta =
|
||||
std::make_unique<JournalDelta>("test.txt"_relpath, JournalDelta::CHANGED);
|
||||
journal.addDelta(std::move(delta));
|
||||
journal.recordChanged("test.txt"_relpath);
|
||||
|
||||
// Sanity check that the latest information matches.
|
||||
auto latest = journal.getLatest();
|
||||
@ -159,9 +150,7 @@ TEST(Journal, destruction_does_not_overflow_stack_on_long_chain) {
|
||||
#endif
|
||||
;
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
auto delta = std::make_unique<JournalDelta>(
|
||||
"foo/bar"_relpath, JournalDelta::CHANGED);
|
||||
journal.addDelta(std::move(delta));
|
||||
journal.recordChanged("foo/bar"_relpath);
|
||||
}
|
||||
}
|
||||
|
||||
@ -175,8 +164,7 @@ TEST(Journal, empty_journal_returns_none_for_stats) {
|
||||
TEST(Journal, basic_journal_stats) {
|
||||
Journal journal;
|
||||
// Journal with 1 entry
|
||||
journal.addDelta(std::make_unique<JournalDelta>(
|
||||
"test.txt"_relpath, JournalDelta::REMOVED));
|
||||
journal.recordRemoved("test.txt"_relpath);
|
||||
auto from1 = journal.getLatest()->fromTime;
|
||||
auto to1 = journal.getLatest()->toTime;
|
||||
auto stats = journal.getStats();
|
||||
@ -186,8 +174,7 @@ TEST(Journal, basic_journal_stats) {
|
||||
ASSERT_EQ(to1, stats->latestTimestamp);
|
||||
|
||||
// Journal with 2 entries
|
||||
journal.addDelta(std::make_unique<JournalDelta>(
|
||||
"test.txt"_relpath, JournalDelta::CREATED));
|
||||
journal.recordCreated("test.txt"_relpath);
|
||||
stats = journal.getStats();
|
||||
auto to2 = journal.getLatest()->toTime;
|
||||
ASSERT_TRUE(stats.has_value());
|
||||
@ -202,11 +189,9 @@ TEST(Journal, memory_usage) {
|
||||
uint64_t prevMem = stats ? stats->memoryUsage : 0;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
if (i % 2 == 0) {
|
||||
journal.addDelta(std::make_unique<JournalDelta>(
|
||||
"test.txt"_relpath, JournalDelta::CREATED));
|
||||
journal.recordCreated("test.txt"_relpath);
|
||||
} else {
|
||||
journal.addDelta(std::make_unique<JournalDelta>(
|
||||
"test.txt"_relpath, JournalDelta::REMOVED));
|
||||
journal.recordRemoved("test.txt"_relpath);
|
||||
}
|
||||
stats = journal.getStats();
|
||||
uint64_t newMem = stats ? stats->memoryUsage : 0;
|
||||
|
Loading…
Reference in New Issue
Block a user