Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion medea/src/app/Controllers/ViewController/viewcontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ ViewController::ViewController()

void ViewController::QueryRunningExperiments()
{
emit vc_displayChartPopup();
if (!isWelcomeScreenShowing()) {
emit vc_displayChartPopup();
}
}

void ViewController::SettingChanged(SETTINGS key, const QVariant& value)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,17 @@ ExperimentDataManager::ExperimentDataManager(const ViewController& vc)
chartDialog_ = new ChartDialog();
dataflowDialog_ = new DataflowDialog();

live_exp_run_id_ = invalid_experiment_id;
last_queried_charts_exp_run_id_ = invalid_experiment_id;
currently_displayed_pulse_exp_run_id_ = invalid_experiment_id;

connect(&vc, &ViewController::modelClosed, this, &ExperimentDataManager::clear);
connect(&vc, &ViewController::vc_displayChartPopup, this, &ExperimentDataManager::showChartInputPopup);
connect(&vc, &ViewController::vc_viewItemsInChart, this, &ExperimentDataManager::filterRequestsBySelectedEntities);

connect(&chartPopup_, &ChartInputPopup::visualiseExperimentRunData, this, &ExperimentDataManager::visualiseSelectedExperimentRun);

connect(&timelineChartView(), &TimelineChartView::lastExperimentRunChartClosed, this, &ExperimentDataManager::experimentRunChartsClosed);

connect(&aggregationProxy(), &AggregationProxy::toastNotification, this, &ExperimentDataManager::toastNotification);
}

Expand Down Expand Up @@ -228,8 +231,6 @@ void ExperimentDataManager::requestWorkloadEvents(const WorkloadRequest& request
toastNotification("Failed to get workload events - " + ex.toString(), "spanner", Notification::Severity::ERROR);
} catch (const std::exception& ex) {
toastNotification("Failed to get workload events - " + QString::fromStdString(ex.what()), "spanner", Notification::Severity::ERROR);
// TODO: Ask Jackson why this causes a crash
//throw;
}
});
futureWatcher->setFuture(future);
Expand Down Expand Up @@ -633,12 +634,17 @@ DataflowDialog& ExperimentDataManager::getDataflowDialog()
/**
* @brief ExperimentDataManager::startTimerLoop
* @param exp_run_id
* @param exp_name
*/
void ExperimentDataManager::startTimerLoop(quint32 exp_run_id)
void ExperimentDataManager::startTimerLoop(quint32 exp_run_id, const QString& exp_name)
{
if (!exp_run_timers_.contains(exp_run_id)) {
auto timer_id = startTimer(default_playback_interval_ms);
exp_run_timers_.insert(exp_run_id, timer_id);
if (!live_exp_run_timers_.contains(exp_run_id)) {
const auto timer_id = startTimer(default_playback_interval_ms);
LiveExperimentTimer timer;
timer.exp_run_id = exp_run_id;
timer.exp_name = exp_name;
timer.timer_id = timer_id;
live_exp_run_timers_.insert(exp_run_id, timer);
}
}

Expand All @@ -648,9 +654,9 @@ void ExperimentDataManager::startTimerLoop(quint32 exp_run_id)
*/
void ExperimentDataManager::stopTimerLoop(quint32 exp_run_id)
{
if (exp_run_timers_.contains(exp_run_id)) {
const auto& timer_id = exp_run_timers_.take(exp_run_id);
killTimer(timer_id);
if (live_exp_run_timers_.contains(exp_run_id)) {
const auto& timer = live_exp_run_timers_.take(exp_run_id);
killTimer(timer.timer_id);
}
}

Expand All @@ -663,18 +669,15 @@ void ExperimentDataManager::timerEvent(QTimerEvent* event)
{
Q_UNUSED(event);

// TODO: Need to discuss what we want happening in the charts when a live experiment(s) is being visualised
// Unlike Pulse, Charts can display data from multiple experiment runs from different experiments at one time
// Previously, the timer was only used for Pulse and was stopped the moment a finished experiment is selected
QSet<quint32> finished_exp_ids;

if (live_exp_run_id_ != invalid_experiment_id) {
const auto exp_run_id = static_cast<quint32>(live_exp_run_id_);
for (const auto& timer : live_exp_run_timers_) {
try {
auto& exp_run_data = getExperimentRunData(live_exp_name_, exp_run_id);
// When the experiment run has an end-time, kill its timer
const auto& exp_run_id = timer.exp_run_id;
auto& exp_run_data = getExperimentRunData(timer.exp_name, exp_run_id);
if (exp_run_data.end_time() != 0) {
stopTimerLoop(exp_run_id);
live_exp_run_id_ = invalid_experiment_id;
// If the experiment run has an end-time, add it to the list of finished experiments
finished_exp_ids.insert(exp_run_id);
} else {
requestExperimentData(ExperimentDataRequestType::ExperimentState, exp_run_id, &exp_run_data);
}
Expand All @@ -683,22 +686,10 @@ void ExperimentDataManager::timerEvent(QTimerEvent* event)
}
}

// TODO: Use the code below when we allow multiple Pulse windows
// Request the displayed experiment run(s)' state every tick interval
/*for (const auto& exp_run_id : exp_run_timers_.keys()) {
const auto& exp_data = getExperimentData(exp_run_id);
if (exp_data) {
const auto& exp_run_data = exp_data->getExperimentRun(exp_run_id);
// When the experiment run has an end-time, kill its timer
if (exp_run_data.end_time() != 0) {
stopTimerLoop(exp_run_id);
} else {
requestExperimentData(ExperimentDataRequestType::ExperimentState, exp_run_id, exp_data);
}
} else {
throw std::invalid_argument("ExperimentDataManager::timerEvent - There is no experiment data for the current experiment run");
}
}*/
// Stop the timers for all the finished experiments
for (const auto& id : finished_exp_ids) {
stopTimerLoop(id);
}
}

/**
Expand Down Expand Up @@ -781,15 +772,17 @@ void ExperimentDataManager::clear()
// Clear request filters
request_filters_.clear();

// Kill any existing timers
for (const auto& exp_run_id : exp_run_timers_.keys()) {
// Kill all existing timers
const auto& live_exp_ids = live_exp_run_timers_.keys();
for (const auto& exp_run_id : live_exp_ids) {
stopTimerLoop(exp_run_id);
}

experiment_data_hash_.clear();
exp_run_timers_.clear();
live_exp_name_.clear();
live_exp_run_id_ = invalid_experiment_id;
live_exp_run_timers_.clear();

last_queried_charts_exp_run_id_ = invalid_experiment_id;
currently_displayed_pulse_exp_run_id_ = invalid_experiment_id;
}

/**
Expand All @@ -809,22 +802,22 @@ void ExperimentDataManager::visualiseSelectedExperimentRun(const AggServerRespon
request_filters_.show_charts = charts;
request_filters_.show_pulse = pulse;

// NOTE: We no longer want to stop it in case the charts are still displaying the live experiment
// TODO: Refactor timer work
// Stop the previous timer if there is one
stopTimerLoop(static_cast<quint32>(live_exp_run_id_));

auto expRunID = static_cast<quint32>(experimentRun.experiment_run_id);
const auto exp_run_id = static_cast<quint32>(experimentRun.experiment_run_id);
if (experimentRun.end_time == 0) {
live_exp_name_ = experimentRun.experiment_name;
live_exp_run_id_ = experimentRun.experiment_run_id;
startTimerLoop(expRunID);
} else {
live_exp_name_.clear();
live_exp_run_id_ = invalid_experiment_id;
// For live experiments, start a timer to continuously request data until the experiment has finished
startTimerLoop(exp_run_id, experimentRun.experiment_name);
}

if (charts) {
last_queried_charts_exp_run_id_ = exp_run_id;
emit showChartsPanel();
}
if (pulse) {
currently_displayed_pulse_exp_run_id_ = exp_run_id;
}

requestExperimentData(ExperimentDataRequestType::ExperimentState, expRunID);
// Request the ExperimentRunState to initialise the Charts and/or graphics items in Pulse
requestExperimentData(ExperimentDataRequestType::ExperimentState, exp_run_id);
}
}

Expand All @@ -839,6 +832,21 @@ void ExperimentDataManager::experimentRunDataUpdated(quint32 exp_run_id, qint64
timelineChartView().updateExperimentRunLastUpdatedTime(exp_run_id, last_updated_time);
}

/**
* @brief ExperimentDataManager::experimentRunChartsClosed
* @param exp_run_id
*/
void ExperimentDataManager::experimentRunChartsClosed(quint32 exp_run_id)
{
if (live_exp_run_timers_.contains(exp_run_id)) {
// If the provided id is live and is the current experiment being displayed in Pulse, do nothing
if (exp_run_id != currently_displayed_pulse_exp_run_id_) {
// If not, stop the timer used for requesting data for the live experiment
stopTimerLoop(exp_run_id);
}
}
}

/**
* @brief ExperimentDataManager::showDataForExperimentRun
* @param exp_run_data
Expand Down Expand Up @@ -929,8 +937,9 @@ void ExperimentDataManager::showChartForSeries(const QPointer<const EventSeries>
{
if (request_filters_.show_charts) {
if (!series.isNull()) {
// NOTE: If one of the displayed charts was manually closed, this will continuously recreate the chart
// everytime new data is received, until the experiment is finished
timelineChartView().addChart(series, exp_run_data);
emit showChartsPanel();
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class ExperimentDataManager : public QObject
ChartDialog& getChartDialog();
DataflowDialog& getDataflowDialog();

void startTimerLoop(quint32 exp_run_id);
void startTimerLoop(quint32 exp_run_id, const QString& exp_name);
void stopTimerLoop(quint32 exp_run_id);

static void toastNotification(const QString& description, const QString& iconName, Notification::Severity severity = Notification::Severity::INFO);
Expand All @@ -66,6 +66,8 @@ private slots:
void visualiseSelectedExperimentRun(const AggServerResponse::ExperimentRun& experimentRun, bool charts, bool pulse);
void experimentRunDataUpdated(quint32 exp_run_id, qint64 last_updated_time);

void experimentRunChartsClosed(quint32 exp_run_id);

protected:
static void constructSingleton(ViewController* vc);

Expand Down Expand Up @@ -150,10 +152,17 @@ private slots:
ChartDialog* chartDialog_ = nullptr;
ChartInputPopup chartPopup_;

struct LiveExperimentTimer {
quint32 exp_run_id;
QString exp_name;
int timer_id;
};

qint32 last_queried_charts_exp_run_id_;
qint32 currently_displayed_pulse_exp_run_id_;

QHash<quint32, LiveExperimentTimer> live_exp_run_timers_;
QHash<QString, MEDEA::ExperimentData*> experiment_data_hash_;
QHash<quint32, int> exp_run_timers_;
QString live_exp_name_;
qint32 live_exp_run_id_;

const ViewController& viewController_;
static ExperimentDataManager* manager_;
Expand Down
48 changes: 27 additions & 21 deletions medea/src/app/Widgets/Charts/Timeline/Chart/timelinechartview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,24 +73,21 @@ void TimelineChartView::addChart(const QPointer<const MEDEA::EventSeries>& serie
throw std::invalid_argument("TimelineChartView::addChart - Series is null.");
}

// If a chart already exists for the series, simply replace the series within the chart
auto chart = charts_.value(series->getID(), nullptr);
if (chart) {
// TODO: If the charts don't get updated live, and the exp run was live when the chart was constructed,
// we will need to update the stored range for the exp run and then update the timeline range
chart->removeSeries(series->getKind());
chart->addSeries(series);
return;
}

const auto exp_run_id = exp_run_data.experiment_run_id();
const auto exp_start_time = exp_run_data.start_time();
const auto& series_id = series->getID();
const auto& series_label = series->getLabel();

experimentRunSeriesCount_[exp_run_id]++;
setTimeRangeForExperimentRun(exp_run_id, exp_start_time, exp_run_data.last_updated_time());

auto chart = charts_.value(series->getID(), nullptr);
if (chart != nullptr) {
updateChart(*chart, series);
updateTimelineRange(false);
return;
}

experimentRunSeriesCount_[exp_run_id]++;
connect(series, &MEDEA::EventSeries::eventAdded, [this]{ update(); });
connect(&exp_run_data, &MEDEA::ExperimentRunData::dataUpdated, [this]{ update(); });

Expand Down Expand Up @@ -136,6 +133,22 @@ void TimelineChartView::addChart(const QPointer<const MEDEA::EventSeries>& serie
updateTimelineRange();
}

/**
* @brief TimelineChartView::updateChart
* @param series
* @param chart
* @throws std::invalid_argument
*/
void TimelineChartView::updateChart(MEDEA::Chart& chart, const QPointer<const MEDEA::EventSeries>& series)
{
if (series.isNull()) {
throw std::invalid_argument("TimelineChartView::updateChart - Series is null.");
}
// Replace the existing series within the chart with the new one
chart.removeSeries(series->getKind());
chart.addSeries(series);
}

/**
* @brief TimelineChartView::removeChart
* @param id
Expand Down Expand Up @@ -163,16 +176,6 @@ void TimelineChartView::removeChart(const QString& id, bool clearing_chart_list)
// Remove the chart label
auto chart_label = chartLabels_.value(id, nullptr);
if (chart_label) {
/* TODO: Un-comment this out if ever we decide to group/parent ChartLabels
auto childrenLabels = chart_label->getChildrenChartLabels();
if (!childrenLabels.isEmpty()) {
// remove/delete chart chart_label's children labels
auto childItr = childrenLabels.begin();
while (childItr != childrenLabels.end()) {
(*childItr)->deleteLater();
childItr = childrenLabels.erase(childItr);
}
} */
chartLabels_.remove(id);
chartLabelList_->removeChartLabel(chart_label);
chart_label->deleteLater();
Expand Down Expand Up @@ -572,6 +575,9 @@ void TimelineChartView::decrementSeriesCountForExperimentRun(quint32 experimentR
return;
}

// Tell the ExperimentDataManager that all the charts for the experiment run with the provided id has been closed
emit lastExperimentRunChartClosed(experimentRunID);

experimentRunSeriesCount_.remove(experimentRunID);
experimentRunTimeRange_.remove(experimentRunID);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class TimelineChartView : public QWidget

bool eventFilter(QObject *watched, QEvent* event) override;

void setTimeDisplayFormat( TIME_DISPLAY_FORMAT format);
void setTimeDisplayFormat(TIME_DISPLAY_FORMAT format);

void addChart(const QPointer<const MEDEA::EventSeries>& series, const MEDEA::ExperimentRunData& exp_run_data);
void removeChart(const QString& id, bool clearing_chart_list = false);
Expand All @@ -52,6 +52,7 @@ class TimelineChartView : public QWidget

signals:
void seriesLegendHovered(MEDEA::ChartDataKind kind);
void lastExperimentRunChartClosed(quint32 exp_run_id);

public slots:
void themeChanged();
Expand All @@ -78,6 +79,7 @@ private slots:
void decrementSeriesCountForExperimentRun(quint32 experimentRunID);
void updateTimelineRange(bool updateDisplayRange = true);

void updateChart(MEDEA::Chart& chart, const QPointer<const MEDEA::EventSeries>& series);
void chartsEmptied();

const QString& getDateTimeDisplayFormat(const MEDEA::ChartDataKind& kind) const;
Expand Down