blob: 8e761c567701a9f8104d63a4b747167369eee5a4 [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "debug_data.h"
#include <lib/syslog/cpp/macros.h>
#include <zircon/assert.h>
#include <zircon/errors.h>
#include <memory>
#include <optional>
#include <utility>
#include <vector>
#include "event_stream.h"
DebugDataImpl::DebugDataImpl(async_dispatcher_t* dispatcher,
std::unique_ptr<AbstractDataProcessor> data_processor)
: weak_factory_(this), data_processor_(std::move(data_processor)), dispatcher_(dispatcher) {}
DebugDataImpl::~DebugDataImpl() = default;
void DebugDataImpl::AddData(
const std::string& moniker, const std::string& test_url, std::string data_sink, zx::vmo vmo,
fidl::InterfaceRequest<fuchsia::debugdata::DebugDataVmoToken> vmo_token) {
zx::channel token_channel = vmo_token.TakeChannel();
auto data_sink_data = DataSinkDump{.data_sink = std::move(data_sink), .vmo = std::move(vmo)};
std::string url_owned(test_url);
// Using a shared pointer here ensures WaitOnce has a reference to itself, preventing it from
// going out of scope.
FX_LOGS(DEBUG) << "Got VMO for " << url_owned;
auto wait = std::make_shared<async::WaitOnce>(token_channel.get(), ZX_CHANNEL_PEER_CLOSED);
wait->Begin(dispatcher_,
[this, wait_cpy = wait, data_sink_data = std::move(data_sink_data),
url_owned = std::move(url_owned), token_channel = std::move(token_channel)](
async_dispatcher_t*, async::WaitOnce*, zx_status_t status,
const zx_packet_signal_t* signal) mutable {
if (status != ZX_OK) {
FX_LOGS(WARNING) << "Error while waiting for VMO token to close: " << status;
}
token_channel.reset();
FX_LOGS(DEBUG) << "Processing VMO for " << url_owned;
data_processor_->ProcessData(std::move(url_owned), std::move(data_sink_data));
});
}
DebugDataImpl::Inner::Inner(fidl::InterfaceRequest<fuchsia::debugdata::DebugData> request,
fxl::WeakPtr<DebugDataImpl> parent, std::string moniker,
std::string test_url, NotifyOnClose notify,
async_dispatcher_t* dispatcher)
: test_url_(std::move(test_url)),
moniker_(std::move(moniker)),
notify_(std::move(notify)),
parent_(std::move(parent)),
binding_(this, std::move(request), dispatcher) {
binding_.set_error_handler([this](zx_status_t /*unused*/) { DestroyAndNotify(); });
}
DebugDataImpl::Inner::~Inner() = default;
std::unique_ptr<DebugDataImpl::Inner> DebugDataImpl::Remove(DebugDataImpl::Inner* ptr) {
auto search = inners_.find(ptr);
if (search != inners_.end()) {
auto inner = std::move(search->second);
inners_.erase(search);
return inner;
}
return nullptr;
}
void DebugDataImpl::Inner::Publish(
::std::string data_sink, zx::vmo data,
fidl::InterfaceRequest<fuchsia::debugdata::DebugDataVmoToken> token) {
FX_CHECK(parent_) << "parent object should not die before this object";
parent_->AddData(moniker_, test_url_, std::move(data_sink), std::move(data), std::move(token));
}
void DebugDataImpl::Inner::LoadConfig(::std::string config_name, LoadConfigCallback callback) {
FX_LOGS(WARNING) << "LoadConfig Called but is not implemented";
CloseConnection(ZX_ERR_NOT_SUPPORTED);
}
void DebugDataImpl::Inner::CloseConnection(zx_status_t epitaph_value) {
binding_.Close(epitaph_value);
DestroyAndNotify();
}
void DebugDataImpl::Inner::DestroyAndNotify() {
std::unique_ptr<DebugDataImpl::Inner> self;
if (parent_) {
self = parent_->Remove(this);
}
if (notify_ != nullptr) {
notify_(std::move(moniker_));
}
// this object dies after this line
}