mirror of
https://github.com/facebook/sapling.git
synced 2024-09-11 10:36:52 +03:00
added JournalStats
Summary: Added JournalStats to start tracking basic stats on the Journal Reviewed By: chadaustin Differential Revision: D15565886 fbshipit-source-id: b7345df377303fc442ecf4c112afa7493bb2dc28
This commit is contained in:
parent
e8daac0e33
commit
5a59af8ae9
@ -87,5 +87,23 @@ bool Journal::isSubscriberValid(uint64_t id) const {
|
||||
return subscribers.find(id) != subscribers.end();
|
||||
}
|
||||
|
||||
std::optional<JournalStats> Journal::getStats() {
|
||||
JournalStats stats;
|
||||
auto curr = getLatest();
|
||||
if (curr == nullptr) {
|
||||
// return None since this is an empty journal
|
||||
return std::nullopt;
|
||||
}
|
||||
stats.latestTimestamp = curr->toTime;
|
||||
stats.earliestTimestamp = curr->fromTime;
|
||||
while (curr != nullptr) {
|
||||
++stats.entryCount;
|
||||
stats.latestTimestamp = std::max(stats.latestTimestamp, curr->toTime);
|
||||
stats.earliestTimestamp = std::min(stats.earliestTimestamp, curr->fromTime);
|
||||
curr = curr->previous;
|
||||
}
|
||||
return stats;
|
||||
}
|
||||
|
||||
} // namespace eden
|
||||
} // namespace facebook
|
||||
|
@ -11,14 +11,23 @@
|
||||
|
||||
#include <folly/Function.h>
|
||||
#include <folly/Synchronized.h>
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
#include "eden/fs/journal/JournalDelta.h"
|
||||
|
||||
namespace facebook {
|
||||
namespace eden {
|
||||
|
||||
/** Contains statistics about the current state of the journal */
|
||||
struct JournalStats {
|
||||
uint64_t entryCount = 0;
|
||||
std::chrono::steady_clock::time_point earliestTimestamp;
|
||||
std::chrono::steady_clock::time_point latestTimestamp;
|
||||
};
|
||||
|
||||
/** The Journal exists to answer questions about how files are changing
|
||||
* over time.
|
||||
*
|
||||
@ -79,6 +88,10 @@ class Journal {
|
||||
void cancelAllSubscribers();
|
||||
bool isSubscriberValid(SubscriberId id) const;
|
||||
|
||||
/** Returns an option that is nullopt if the Journal is empty or an option
|
||||
* that contains valid JournalStats if the Journal is non-empty*/
|
||||
std::optional<JournalStats> getStats();
|
||||
|
||||
private:
|
||||
struct DeltaState {
|
||||
/** The sequence number that we'll use for the next entry
|
||||
|
@ -171,3 +171,86 @@ TEST(Journal, destruction_does_not_overflow_stack_on_long_chain) {
|
||||
journal.addDelta(std::move(delta));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(Journal, empty_journal_returns_none_for_stats) {
|
||||
// Empty journal returns None for stats
|
||||
Journal journal;
|
||||
auto stats = journal.getStats();
|
||||
ASSERT_FALSE(stats.has_value());
|
||||
}
|
||||
|
||||
TEST(Journal, basic_journal_stats) {
|
||||
Journal journal;
|
||||
// Journal with 1 entry
|
||||
journal.addDelta(std::make_unique<JournalDelta>(
|
||||
"test.txt"_relpath, JournalDelta::REMOVED));
|
||||
auto from1 = journal.getLatest()->fromTime;
|
||||
auto to1 = journal.getLatest()->toTime;
|
||||
auto stats = journal.getStats();
|
||||
ASSERT_TRUE(stats.has_value());
|
||||
ASSERT_EQ(1, stats->entryCount);
|
||||
ASSERT_EQ(from1, stats->earliestTimestamp);
|
||||
ASSERT_EQ(to1, stats->latestTimestamp);
|
||||
|
||||
// Journal with 2 entries
|
||||
journal.addDelta(std::make_unique<JournalDelta>(
|
||||
"test.txt"_relpath, JournalDelta::CREATED));
|
||||
stats = journal.getStats();
|
||||
auto to2 = journal.getLatest()->toTime;
|
||||
ASSERT_TRUE(stats.has_value());
|
||||
ASSERT_EQ(2, stats->entryCount);
|
||||
ASSERT_EQ(from1, stats->earliestTimestamp);
|
||||
ASSERT_EQ(to2, stats->latestTimestamp);
|
||||
}
|
||||
|
||||
TEST(Journal, merge_journal_stats) {
|
||||
Journal journal;
|
||||
journal.addDelta(std::make_unique<JournalDelta>(
|
||||
"test.txt"_relpath, JournalDelta::REMOVED));
|
||||
auto from1 = journal.getLatest()->fromTime;
|
||||
journal.addDelta(std::make_unique<JournalDelta>(
|
||||
"test.txt"_relpath, JournalDelta::CREATED));
|
||||
auto stats = journal.getStats();
|
||||
auto to2 = journal.getLatest()->toTime;
|
||||
|
||||
// Journal with 2 entries merged into 1 entry
|
||||
auto latest = journal.getLatest();
|
||||
journal.replaceJournal(latest->merge());
|
||||
stats = journal.getStats();
|
||||
ASSERT_TRUE(stats.has_value());
|
||||
ASSERT_EQ(1, stats->entryCount);
|
||||
ASSERT_EQ(from1, stats->earliestTimestamp);
|
||||
ASSERT_EQ(to2, stats->latestTimestamp);
|
||||
}
|
||||
|
||||
TEST(Journal, prune_journal_stats) {
|
||||
Journal journal;
|
||||
journal.addDelta(std::make_unique<JournalDelta>(
|
||||
"test.txt"_relpath, JournalDelta::REMOVED));
|
||||
journal.addDelta(std::make_unique<JournalDelta>(
|
||||
"test.txt"_relpath, JournalDelta::CREATED));
|
||||
auto stats = journal.getStats();
|
||||
auto from2 = journal.getLatest()->fromTime;
|
||||
auto to2 = journal.getLatest()->toTime;
|
||||
auto latest = journal.getLatest();
|
||||
// Journal with the first entry pruned
|
||||
journal.replaceJournal(latest->merge(2, true));
|
||||
stats = journal.getStats();
|
||||
ASSERT_TRUE(stats.has_value());
|
||||
ASSERT_EQ(1, stats->entryCount);
|
||||
ASSERT_EQ(from2, stats->earliestTimestamp);
|
||||
ASSERT_EQ(to2, stats->latestTimestamp);
|
||||
}
|
||||
|
||||
TEST(Journal, fully_pruned_journal_stats) {
|
||||
Journal journal;
|
||||
journal.addDelta(std::make_unique<JournalDelta>(
|
||||
"test.txt"_relpath, JournalDelta::REMOVED));
|
||||
journal.addDelta(std::make_unique<JournalDelta>(
|
||||
"test.txt"_relpath, JournalDelta::CREATED));
|
||||
auto latest = journal.getLatest();
|
||||
// Journal with all entries pruned
|
||||
journal.replaceJournal(latest->merge(3, true));
|
||||
auto stats = journal.getStats();
|
||||
ASSERT_FALSE(stats.has_value());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user