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:
Jake Crouch 2019-06-19 15:12:50 -07:00 committed by Facebook Github Bot
parent 73e2c2a997
commit 26a6e91e05
8 changed files with 125 additions and 70 deletions

View File

@ -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 {

View File

@ -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;

View File

@ -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

View File

@ -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);
}
}

View File

@ -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();

View File

@ -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 */

View File

@ -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;

View File

@ -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;