[ledger] Dynamicize Inspect API use
Test: Commit queue all the way.
Change-Id: Ibd2b70124f7b33eb88f11729ca7416dc914cdf0c
diff --git a/bin/ledger/app/app.cc b/bin/ledger/app/app.cc
index 038d1e2..864ae37 100644
--- a/bin/ledger/app/app.cc
+++ b/bin/ledger/app/app.cc
@@ -21,6 +21,7 @@
#include <trace-provider/provider.h>
#include <zircon/device/vfs.h>
+#include "peridot/bin/ledger/app/constants.h"
#include "peridot/bin/ledger/app/ledger_repository_factory_impl.h"
#include "peridot/bin/ledger/cobalt/cobalt.h"
#include "peridot/bin/ledger/environment/environment.h"
@@ -110,8 +111,17 @@
startup_context_->outgoing().object_dir()->set_prop(
"statistic_gathering", app_params_.disable_statistics ? "off" : "on");
+ startup_context_->outgoing().object_dir()->set_children_callback(
+ {kRepositoriesInspectPathComponent},
+ [this](component::Object::ObjectVector* out) {
+ factory_impl_->GetChildren(out);
+ });
+
loop_.Run();
+ startup_context_->outgoing().object_dir()->set_children_callback(
+ {kRepositoriesInspectPathComponent}, nullptr);
+
return true;
}
diff --git a/bin/ledger/app/constants.h b/bin/ledger/app/constants.h
index 7b3da32..cc84c4c 100644
--- a/bin/ledger/app/constants.h
+++ b/bin/ledger/app/constants.h
@@ -24,6 +24,10 @@
// The serialization version of PageUsage DB.
inline constexpr fxl::StringView kPageUsageDbSerializationVersion = "1";
+inline constexpr char kRepositoriesInspectPathComponent[] = "repositories";
+inline constexpr char kRequestsInspectPathComponent[] = "requests";
+inline constexpr char kLedgersInspectPathComponent[] = "ledgers";
+
} // namespace ledger
#endif // PERIDOT_BIN_LEDGER_APP_CONSTANTS_H_
diff --git a/bin/ledger/app/ledger_repository_factory_impl.cc b/bin/ledger/app/ledger_repository_factory_impl.cc
index e245a89..62554f1 100644
--- a/bin/ledger/app/ledger_repository_factory_impl.cc
+++ b/bin/ledger/app/ledger_repository_factory_impl.cc
@@ -9,6 +9,7 @@
#include <unistd.h>
#include <lib/backoff/exponential_backoff.h>
+#include <lib/component/cpp/expose.h>
#include <lib/component/cpp/object_dir.h>
#include <lib/fdio/util.h>
#include <lib/fit/function.h>
@@ -24,6 +25,7 @@
#include <zircon/processargs.h>
#include <zircon/syscalls.h>
+#include "peridot/bin/ledger/app/constants.h"
#include "peridot/bin/ledger/app/disk_cleanup_manager_impl.h"
#include "peridot/bin/ledger/app/serialization_version.h"
#include "peridot/bin/ledger/cloud_sync/impl/user_sync_impl.h"
@@ -76,8 +78,6 @@
constexpr fxl::StringView kStagingPath = "staging";
constexpr fxl::StringView kNamePath = "name";
-constexpr char kRepositoriesPath[] = "repositories";
-
bool GetRepositoryName(rng::Random* random, const DetachedPath& content_path,
std::string* name) {
DetachedPath name_path = content_path.SubPath(kNamePath);
@@ -125,6 +125,15 @@
}
};
+ // Forwards to the Inspect method of the wrapped LedgerRepositoryImpl, if the
+ // wrapped LedgerRepositoryImpl is present. Otherwise does nothing.
+ void Inspect(std::string display_name,
+ component::Object::ObjectVector* out) const {
+ if (ledger_repository_) {
+ ledger_repository_->Inspect(std::move(display_name), out);
+ }
+ }
+
// Keeps track of |request| and |callback|. Binds |request| and fires
// |callback| when the repository is available or an error occurs.
void BindRepository(
@@ -236,6 +245,13 @@
LedgerRepositoryFactoryImpl::~LedgerRepositoryFactoryImpl() {}
+void LedgerRepositoryFactoryImpl::GetChildren(
+ component::Object::ObjectVector* out) {
+ for (const auto& [name, container] : repositories_) {
+ container.Inspect(convert::ToHex(name), out);
+ }
+}
+
void LedgerRepositoryFactoryImpl::GetRepository(
zx::channel repository_handle,
fidl::InterfaceHandle<cloud_provider::CloudProvider> cloud_provider,
@@ -306,15 +322,10 @@
}
DiskCleanupManagerImpl* disk_cleanup_manager_ptr = disk_cleanup_manager.get();
- component::ExposedObject repository_exposed_object(
- convert::ToHex(repository_information.name));
- repository_exposed_object.set_parent(
- inspect_object_dir_.find({kRepositoriesPath}));
auto repository = std::make_unique<LedgerRepositoryImpl>(
- std::move(repository_exposed_object), repository_information.ledgers_path,
- environment_, std::move(db_factory), std::move(watchers),
- std::move(user_sync), std::move(disk_cleanup_manager),
- disk_cleanup_manager_ptr);
+ repository_information.ledgers_path, environment_, std::move(db_factory),
+ std::move(watchers), std::move(user_sync),
+ std::move(disk_cleanup_manager), disk_cleanup_manager_ptr);
disk_cleanup_manager_ptr->SetPageEvictionDelegate(repository.get());
container->SetRepository(Status::OK, std::move(repository));
}
@@ -334,7 +345,7 @@
user_config.user_directory = repository_information.content_path;
user_config.cloud_provider = std::move(cloud_provider_ptr);
fit::closure on_version_mismatch = [this, repository_information]() mutable {
- OnVersionMismatch(std::move(repository_information));
+ OnVersionMismatch(repository_information);
};
auto cloud_sync = std::make_unique<cloud_sync::UserSyncImpl>(
environment_, std::move(user_config), environment_->MakeBackoff(),
diff --git a/bin/ledger/app/ledger_repository_factory_impl.h b/bin/ledger/app/ledger_repository_factory_impl.h
index d43e888..86569ff 100644
--- a/bin/ledger/app/ledger_repository_factory_impl.h
+++ b/bin/ledger/app/ledger_repository_factory_impl.h
@@ -15,6 +15,7 @@
#include <lib/callback/auto_cleanable.h>
#include <lib/callback/cancellable.h>
#include <lib/callback/managed_container.h>
+#include <lib/component/cpp/expose.h>
#include <lib/fxl/files/unique_fd.h>
#include <lib/fxl/macros.h>
@@ -40,6 +41,10 @@
component::ObjectDir inspect_object_dir);
~LedgerRepositoryFactoryImpl() override;
+ // Populates |out| with children to be traversed (or not) during an
+ // inspection.
+ void GetChildren(component::Object::ObjectVector* out);
+
// LedgerRepositoryFactoryErrorNotifierDelegate:
void GetRepository(
zx::channel repository_handle,
diff --git a/bin/ledger/app/ledger_repository_factory_impl_unittest.cc b/bin/ledger/app/ledger_repository_factory_impl_unittest.cc
index 4ef4e5f..87ce204 100644
--- a/bin/ledger/app/ledger_repository_factory_impl_unittest.cc
+++ b/bin/ledger/app/ledger_repository_factory_impl_unittest.cc
@@ -14,6 +14,7 @@
#include "gmock/gmock.h"
#include "gtest/gtest.h"
+#include "peridot/bin/ledger/app/constants.h"
#include "peridot/bin/ledger/testing/inspect.h"
#include "peridot/bin/ledger/testing/test_with_environment.h"
#include "peridot/lib/scoped_tmpfs/scoped_tmpfs.h"
@@ -28,18 +29,26 @@
using ::testing::UnorderedElementsAre;
constexpr fxl::StringView kObjectsName = "test objects";
-constexpr fxl::StringView kRepositoriesName = "repositories";
constexpr fxl::StringView kUserID = "test user ID";
class LedgerRepositoryFactoryImplTest : public TestWithEnvironment {
public:
LedgerRepositoryFactoryImplTest() {
- object_dir_ = component::ObjectDir::Make({kObjectsName.data(), kObjectsName.size()});
+ object_dir_ =
+ component::ObjectDir::Make({kObjectsName.data(), kObjectsName.size()});
repository_factory_ = std::make_unique<LedgerRepositoryFactoryImpl>(
&environment_, nullptr, object_dir_);
+ object_dir_.set_children_callback(
+ {kRepositoriesInspectPathComponent},
+ [this](component::Object::ObjectVector* out) {
+ repository_factory_->GetChildren(out);
+ });
}
- ~LedgerRepositoryFactoryImplTest() override {}
+ ~LedgerRepositoryFactoryImplTest() override {
+ object_dir_.set_children_callback({kRepositoriesInspectPathComponent},
+ nullptr);
+ }
protected:
::testing::AssertionResult CreateDirectory(std::string name);
@@ -145,7 +154,7 @@
bool success = false;
object_dir_.object()->OpenChild(
- kRepositoriesName.ToString(), repositories_inspect_ptr->NewRequest(),
+ kRepositoriesInspectPathComponent, repositories_inspect_ptr->NewRequest(),
callback::Capture(callback::SetWhenCalled(&callback_called), &success));
RunLoopUntilIdle();
@@ -224,7 +233,7 @@
EXPECT_EQ(kObjectsName, *object.name);
EXPECT_THAT(*object.properties, IsEmpty());
EXPECT_THAT(*object.metrics, IsEmpty());
- EXPECT_THAT(*children, IsEmpty());
+ EXPECT_THAT(*children, ElementsAre(kRepositoriesInspectPathComponent));
}
TEST_F(LedgerRepositoryFactoryImplTest,
@@ -246,10 +255,9 @@
ledger_internal::LedgerRepositoryPtr second_ledger_repository_ptr;
ledger_internal::LedgerRepositoryPtr first_again_ledger_repository_ptr;
- // Bindings to Inspect API "Inspect" objects. Over the course of the test the
- // top-level object_dir_ will gain a "repositories" child which itself will
- // gain two children (one for each created repository, with names chosen by
- // the LedgerRepositoryFactoryImpl under test).
+ // Bindings to Inspect API "Inspect" objects. Because the Ledger objects'
+ // parent-child relationships are dynamically computed, these need to be
+ // unbound and rebound for each inspection of the repositories.
fuchsia::inspect::InspectPtr repositories_inspect_ptr;
fuchsia::inspect::InspectPtr first_repository_inspect_ptr;
fuchsia::inspect::InspectPtr second_repository_inspect_ptr;
@@ -267,7 +275,7 @@
// it is listed) and that it was requested once.
ASSERT_TRUE(CallGetRepository(first_directory, &first_ledger_repository_ptr));
ASSERT_TRUE(ListTopLevelChildren(&children_names));
- EXPECT_THAT(*children_names, ElementsAre(kRepositoriesName.ToString()));
+ EXPECT_THAT(*children_names, ElementsAre(kRepositoriesInspectPathComponent));
ASSERT_TRUE(OpenTopLevelRepositoriesChild(&repositories_inspect_ptr));
ASSERT_TRUE(ListChildren(&repositories_inspect_ptr, &children_names));
EXPECT_THAT(*children_names, SizeIs(1));
@@ -285,6 +293,9 @@
// repositories were each requested once.
ASSERT_TRUE(
CallGetRepository(second_directory, &second_ledger_repository_ptr));
+ ASSERT_TRUE(ListTopLevelChildren(&children_names));
+ EXPECT_THAT(*children_names, ElementsAre(kRepositoriesInspectPathComponent));
+ ASSERT_TRUE(OpenTopLevelRepositoriesChild(&repositories_inspect_ptr));
ASSERT_TRUE(ListChildren(&repositories_inspect_ptr, &children_names));
EXPECT_THAT(*children_names, SizeIs(2));
second_repository_name =
@@ -295,6 +306,8 @@
EXPECT_THAT(*children_names, UnorderedElementsAre(first_repository_name,
second_repository_name));
EXPECT_THAT(*second_repository_name, Not(IsEmpty()));
+ ASSERT_TRUE(OpenChild(&repositories_inspect_ptr, first_repository_name,
+ &first_repository_inspect_ptr));
ASSERT_TRUE(OpenChild(&repositories_inspect_ptr, second_repository_name,
&second_repository_inspect_ptr));
ASSERT_TRUE(ReadData(&first_repository_inspect_ptr, &object));
@@ -310,9 +323,16 @@
// respectively.
ASSERT_TRUE(
CallGetRepository(first_directory, &first_again_ledger_repository_ptr));
+ ASSERT_TRUE(ListTopLevelChildren(&children_names));
+ EXPECT_THAT(*children_names, ElementsAre(kRepositoriesInspectPathComponent));
+ ASSERT_TRUE(OpenTopLevelRepositoriesChild(&repositories_inspect_ptr));
ASSERT_TRUE(ListChildren(&repositories_inspect_ptr, &children_names));
EXPECT_THAT(*children_names, UnorderedElementsAre(first_repository_name,
second_repository_name));
+ ASSERT_TRUE(OpenChild(&repositories_inspect_ptr, first_repository_name,
+ &first_repository_inspect_ptr));
+ ASSERT_TRUE(OpenChild(&repositories_inspect_ptr, second_repository_name,
+ &second_repository_inspect_ptr));
ASSERT_TRUE(ReadData(&first_repository_inspect_ptr, &object));
EXPECT_EQ(first_repository_name, *object.name);
ExpectRequestsMetric(&object, 2UL);
diff --git a/bin/ledger/app/ledger_repository_impl.cc b/bin/ledger/app/ledger_repository_impl.cc
index 1bab80a..a0ccbeb 100644
--- a/bin/ledger/app/ledger_repository_impl.cc
+++ b/bin/ledger/app/ledger_repository_impl.cc
@@ -4,8 +4,11 @@
#include "peridot/bin/ledger/app/ledger_repository_impl.h"
+#include <lib/component/cpp/expose.h>
+#include <lib/component/cpp/object_dir.h>
#include <trace/event.h>
+#include "peridot/bin/ledger/app/constants.h"
#include "peridot/bin/ledger/app/page_utils.h"
#include "peridot/bin/ledger/cloud_sync/impl/ledger_sync_impl.h"
#include "peridot/bin/ledger/p2p_sync/public/ledger_communicator.h"
@@ -23,14 +26,13 @@
} // namespace
LedgerRepositoryImpl::LedgerRepositoryImpl(
- component::ExposedObject exposed_object, DetachedPath content_path,
- Environment* environment, std::unique_ptr<storage::DbFactory> db_factory,
+ DetachedPath content_path, Environment* environment,
+ std::unique_ptr<storage::DbFactory> db_factory,
std::unique_ptr<SyncWatcherSet> watchers,
std::unique_ptr<sync_coordinator::UserSync> user_sync,
std::unique_ptr<DiskCleanupManager> disk_cleanup_manager,
PageUsageListener* page_usage_listener)
- : exposed_object_(std::move(exposed_object)),
- content_path_(std::move(content_path)),
+ : content_path_(std::move(content_path)),
environment_(environment),
db_factory_(std::move(db_factory)),
encryption_service_factory_(environment),
@@ -43,15 +45,25 @@
ledger_repository_debug_bindings_.set_empty_set_handler(
[this] { CheckEmpty(); });
disk_cleanup_manager_->set_on_empty([this] { CheckEmpty(); });
- exposed_object_.object_dir().set_metric("requests", component::UIntMetric(0));
}
LedgerRepositoryImpl::~LedgerRepositoryImpl() {}
+void LedgerRepositoryImpl::Inspect(std::string display_name,
+ component::Object::ObjectVector* out) const {
+ auto object_dir = component::ObjectDir::Make(std::move(display_name));
+ object_dir.set_metric({kRequestsInspectPathComponent},
+ component::UIntMetric(bindings_.size()));
+ object_dir.set_children_callback(
+ [/*this*/](component::Object::ObjectVector* out) {
+ // TODO(nathaniel): This is the next level down of inspection...
+ });
+ out->push_back(object_dir.object());
+}
+
void LedgerRepositoryImpl::BindRepository(
fidl::InterfaceRequest<ledger_internal::LedgerRepository>
repository_request) {
- exposed_object_.object_dir().add_metric("requests", 1);
bindings_.emplace(this, std::move(repository_request));
}
diff --git a/bin/ledger/app/ledger_repository_impl.h b/bin/ledger/app/ledger_repository_impl.h
index 7df63da..5e9ef79 100644
--- a/bin/ledger/app/ledger_repository_impl.h
+++ b/bin/ledger/app/ledger_repository_impl.h
@@ -7,8 +7,8 @@
#include <fuchsia/ledger/internal/cpp/fidl.h>
#include <fuchsia/modular/auth/cpp/fidl.h>
-#include <garnet/public/lib/component/cpp/exposed_object.h>
#include <lib/callback/auto_cleanable.h>
+#include <lib/component/cpp/expose.h>
#include <lib/fidl/cpp/interface_ptr_set.h>
#include <lib/fit/function.h>
#include <lib/fxl/files/unique_fd.h>
@@ -38,8 +38,7 @@
public:
// Creates a new LedgerRepositoryImpl object. Guarantees that |db_factory|
// will outlive the given |disk_cleanup_manager|.
- LedgerRepositoryImpl(component::ExposedObject exposed_object,
- DetachedPath content_path, Environment* environment,
+ LedgerRepositoryImpl(DetachedPath content_path, Environment* environment,
std::unique_ptr<storage::DbFactory> db_factory,
std::unique_ptr<SyncWatcherSet> watchers,
std::unique_ptr<sync_coordinator::UserSync> user_sync,
@@ -47,6 +46,11 @@
PageUsageListener* page_usage_listener);
~LedgerRepositoryImpl() override;
+ // Satisfies an inspection by adding to |out| an object with properties,
+ // metrics, and (callbacks affording access to) children of its own.
+ void Inspect(std::string display_name,
+ component::Object::ObjectVector* out) const;
+
void set_on_empty(fit::closure on_empty_callback) {
on_empty_callback_ = std::move(on_empty_callback);
}
@@ -101,7 +105,6 @@
fidl::InterfaceRequest<ledger_internal::LedgerDebug> request,
GetLedgerDebugCallback callback) override;
- component::ExposedObject exposed_object_;
const DetachedPath content_path_;
Environment* const environment_;
std::unique_ptr<storage::DbFactory> db_factory_;
diff --git a/bin/ledger/app/ledger_repository_impl_unittest.cc b/bin/ledger/app/ledger_repository_impl_unittest.cc
index c3d7a31..378a9e6 100644
--- a/bin/ledger/app/ledger_repository_impl_unittest.cc
+++ b/bin/ledger/app/ledger_repository_impl_unittest.cc
@@ -7,7 +7,7 @@
#include <fuchsia/inspect/cpp/fidl.h>
#include <lib/callback/capture.h>
#include <lib/callback/set_when_called.h>
-#include <lib/component/cpp/object_dir.h>
+#include <lib/component/cpp/expose.h>
#include <lib/fit/function.h>
#include <lib/fsl/vmo/strings.h>
#include <lib/fxl/functional/make_copyable.h>
@@ -34,12 +34,9 @@
auto fake_page_eviction_manager =
std::make_unique<FakeDiskCleanupManager>();
disk_cleanup_manager_ = fake_page_eviction_manager.get();
- component::ExposedObject exposed_object = component::ExposedObject("test");
- object_dir_ = exposed_object.object_dir();
repository_ = std::make_unique<LedgerRepositoryImpl>(
- std::move(exposed_object), DetachedPath(tmpfs_.root_fd()),
- &environment_,
+ DetachedPath(tmpfs_.root_fd()), &environment_,
std::make_unique<storage::fake::FakeDbFactory>(dispatcher()), nullptr,
nullptr, std::move(fake_page_eviction_manager), disk_cleanup_manager_);
}
@@ -49,7 +46,6 @@
protected:
scoped_tmpfs::ScopedTmpFS tmpfs_;
FakeDiskCleanupManager* disk_cleanup_manager_;
- component::ObjectDir object_dir_;
std::unique_ptr<LedgerRepositoryImpl> repository_;
private:
@@ -87,27 +83,48 @@
}
TEST_F(LedgerRepositoryImplTest, InspectAPIRequestsMetricOnMultipleBindings) {
+ // When nothing has bound to the repository, check that the "requests" metric
+ // is present and is zero.
bool zeroth_callback_called = false;
fuchsia::inspect::Object zeroth_read_object;
- object_dir_.object()->ReadData(callback::Capture(
+ component::Object::ObjectVector zeroth_out;
+
+ repository_->Inspect("zeroth", &zeroth_out);
+
+ ASSERT_EQ(1UL, zeroth_out.size());
+ zeroth_out.at(0).get()->ReadData(callback::Capture(
callback::SetWhenCalled(&zeroth_callback_called), &zeroth_read_object));
EXPECT_TRUE(zeroth_callback_called);
ExpectRequestsMetric(&zeroth_read_object, 0UL);
+ // When one binding has been made to the repository, check that the "requests"
+ // metric is present and is one.
ledger_internal::LedgerRepositoryPtr first_ledger_repository_ptr;
- repository_->BindRepository(first_ledger_repository_ptr.NewRequest());
bool first_callback_called = false;
fuchsia::inspect::Object first_read_object;
- object_dir_.object()->ReadData(callback::Capture(
+ component::Object::ObjectVector first_out;
+ repository_->BindRepository(first_ledger_repository_ptr.NewRequest());
+
+ repository_->Inspect("first", &first_out);
+
+ ASSERT_EQ(1UL, first_out.size());
+ first_out.at(0).get()->ReadData(callback::Capture(
callback::SetWhenCalled(&first_callback_called), &first_read_object));
EXPECT_TRUE(first_callback_called);
ExpectRequestsMetric(&first_read_object, 1UL);
+ // When two bindings have been made to the repository, check that the
+ // "requests" metric is present and is two.
ledger_internal::LedgerRepositoryPtr second_ledger_repository_ptr;
- repository_->BindRepository(second_ledger_repository_ptr.NewRequest());
bool second_callback_called = false;
fuchsia::inspect::Object second_read_object;
- object_dir_.object()->ReadData(callback::Capture(
+ component::Object::ObjectVector second_out;
+ repository_->BindRepository(second_ledger_repository_ptr.NewRequest());
+
+ repository_->Inspect("second", &second_out);
+
+ ASSERT_EQ(1UL, second_out.size());
+ second_out.at(0).get()->ReadData(callback::Capture(
callback::SetWhenCalled(&second_callback_called), &second_read_object));
EXPECT_TRUE(second_callback_called);
ExpectRequestsMetric(&second_read_object, 2UL);
diff --git a/bin/ledger/testing/inspect.cc b/bin/ledger/testing/inspect.cc
index dc9be8b..c85c22a 100644
--- a/bin/ledger/testing/inspect.cc
+++ b/bin/ledger/testing/inspect.cc
@@ -7,6 +7,7 @@
#include <fuchsia/inspect/cpp/fidl.h>
#include "gtest/gtest.h"
+#include "peridot/bin/ledger/app/constants.h"
namespace ledger {
@@ -17,7 +18,7 @@
unsigned long extra_requests_found = 0UL;
unsigned long requests = 0UL;
for (auto& index : *object->metrics) {
- if (index.key == "requests") {
+ if (index.key == kRequestsInspectPathComponent) {
if (!requests_found) {
requests_found = true;
requests = index.value.uint_value();