aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorToni Uhlig <Toni.Uhlig@tq-group.com>2017-12-05 16:07:23 +0100
committerToni Uhlig <Toni.Uhlig@tq-group.com>2017-12-05 16:28:14 +0100
commit3c79f311cfd32f7f4508b6225a90d9caf567e923 (patch)
treee804539678bfbfa0664aa44e5bdc9309db5e94be
parentaca4821babd7b6eed20b114a9f6c26e8f978198f (diff)
print job timings (average, total, estimated remaining time), removed developer info
-rw-r--r--AUTHORS2
-rw-r--r--src/JobQueue.cpp22
-rw-r--r--src/JobQueue.hpp8
-rw-r--r--src/UpdateGUI.cpp66
4 files changed, 79 insertions, 19 deletions
diff --git a/AUTHORS b/AUTHORS
index 29799ac..11f711d 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,3 +1 @@
Toni Uhlig
-Valeri Budjko
-Theres Teichmann
diff --git a/src/JobQueue.cpp b/src/JobQueue.cpp
index 8395353..4f85619 100644
--- a/src/JobQueue.cpp
+++ b/src/JobQueue.cpp
@@ -28,6 +28,15 @@ void Queue::Report(const Job::JobEvents& cmd, const wxString& sArg, int iArg)
m_pParent->AddPendingEvent(evt);
}
+void Queue::ReportDone(const JobReport& jobReport, const wxString& sArg, int iArg)
+{
+ wxCommandEvent evt(wxEVT_THREAD, Job::eID_THREAD_JOB_DONE);
+ evt.SetString(sArg);
+ evt.SetInt(iArg);
+ evt.SetClientObject(new JobReport(jobReport));
+ m_pParent->AddPendingEvent(evt);
+}
+
wxThread::ExitCode WorkerThread::doWork()
{
Sleep(1000);
@@ -41,11 +50,14 @@ wxThread::ExitCode WorkerThread::doWork()
void WorkerThread::doJob()
{
int rv;
+ std::time_t jobStart, jobEnd;
+ unsigned diffTime;
std::string err;
UpdateFactory uf;
Job job = m_pQueue->Pop();
m_pQueue->incBusyWorker();
+ jobStart = std::time(nullptr);
/* process the job which was started by the GUI */
switch(job.cmdEvent)
@@ -128,8 +140,12 @@ void WorkerThread::doJob()
default:
break;
}
- m_pQueue->Report(Job::eID_THREAD_JOB_DONE,
- wxString::Format(wxT("Job #%d: finished."),
- job.cmdArgs.jobid), m_ID);
+
+ jobEnd = std::time(nullptr);
+ diffTime = std::difftime(jobEnd, jobStart);
+
+ m_pQueue->ReportDone(JobReport(diffTime),
+ wxString::Format(wxT("Job #%d: finished. Time consumed: %umin %usec"),
+ job.cmdArgs.jobid, (diffTime / 60), (diffTime % 60)), m_ID);
m_pQueue->decBusyWorker();
}
diff --git a/src/JobQueue.hpp b/src/JobQueue.hpp
index 519903d..ddf2f33 100644
--- a/src/JobQueue.hpp
+++ b/src/JobQueue.hpp
@@ -39,6 +39,13 @@ struct JobArgs
std::string password;
};
+struct JobReport : public wxClientData
+{
+ JobReport(double jTime)
+ : jobTime(jTime) {}
+ double jobTime;
+};
+
struct Job
{
enum JobEvents
@@ -76,6 +83,7 @@ public:
Job Pop();
/* report back to parent */
void Report(const Job::JobEvents& cmd, const wxString& sArg = wxEmptyString, int iArg = 0);
+ void ReportDone(const JobReport& jobReport, const wxString& sArg = wxEmptyString, int iArg = 0);
size_t Stacksize()
{
wxMutexLocker lock(m_MutexQueue);
diff --git a/src/UpdateGUI.cpp b/src/UpdateGUI.cpp
index 5620020..a411ad5 100644
--- a/src/UpdateGUI.cpp
+++ b/src/UpdateGUI.cpp
@@ -6,6 +6,7 @@
#include <iostream>
#include <iomanip>
+#include <tuple>
#include <chrono>
#include <ctime>
#include <wx/aboutdlg.h>
@@ -210,8 +211,6 @@ void UpdateGUIFrame::OnAbout(wxCommandEvent& event)
aboutInfo.SetCopyright("(C) 2017");
aboutInfo.SetWebSite(PACKAGE_URL);
aboutInfo.AddDeveloper("Toni Uhlig");
- aboutInfo.AddDeveloper("Valeri Budjko");
- aboutInfo.AddDeveloper("Theres Teichmann");
aboutInfo.SetLicense(wxString(
"TQ-Systems Software License Agreement Version 1.0.1\n\n"
"wxWidgets: wxWindows Library Licence, Version 3.1\n"
@@ -228,6 +227,7 @@ void UpdateGUIFrame::OnAbout(wxCommandEvent& event)
void UpdateGUIFrame::OnEditor(wxCommandEvent& event)
{
+ /* StatusLog Events: not used atm */
}
void UpdateGUIFrame::OnUpdateFile(wxCommandEvent& event)
@@ -266,10 +266,12 @@ void UpdateGUIFrame::OnImportCSV(wxCommandEvent& event)
tLog(RTL_DEFAULT, wxString::Format(wxT("CSV File: \"%s\""), openFileDialog.GetPath()));
loadUpdateFactoriesFromCSV(openFileDialog.GetPath(), imgEntry->GetValue(), uf, error_list);
+ /* check for CSV read errors */
for (auto& errstr : error_list) {
tLog(RTL_RED, wxString::Format(wxT("CSV read error: \"%s\""), errstr));
}
+ /* add all csv jobs to the job queue */
jobid = rand();
for (auto *u : uf) {
jobs->AddJob(Job(Job::eID_THREAD_JOB, JobArgs(jobid, *u)));
@@ -300,6 +302,7 @@ void UpdateGUIFrame::OnUpdate(wxCommandEvent& event)
str = ipEntry->GetValue();
/* parse multiple hostname:port combinations */
loadUpdateFactoriesFromStr(str, imgEntry->GetValue(), pwEntry->GetValue(), uf);
+ /* add all jobs to the job queue */
int jobid = rand();
for (auto *u : uf) {
std::ostringstream log;
@@ -307,8 +310,7 @@ void UpdateGUIFrame::OnUpdate(wxCommandEvent& event)
tLog(RTL_DEFAULT, log.str().c_str());
jobs->AddJob(Job(Job::eID_THREAD_JOB, JobArgs(jobid, *u)));
- delete u;
-
+ delete u; /* do not leak heap memory */
jobid++;
}
}
@@ -323,12 +325,38 @@ void UpdateGUIFrame::OnNavigationKey(wxNavigationKeyEvent& event)
}
}
+/* return a tuple(avgJobTime[sec], totJobTime[min], estJobTime[min]) */
+static std::tuple<unsigned, unsigned, unsigned>
+calcJobTimingsAvgTotEst(Queue& jobs, size_t parallelJobCount, JobReport& jobReport, std::vector<unsigned>& jobTimings)
+{
+ unsigned avg = 0, tot = 0, est;
+ unsigned jobTime = jobReport.jobTime;
+
+ jobTimings.push_back(jobTime);
+ /* calculate an average/total */
+ for (auto& time : jobTimings) {
+ avg += time;
+ tot += time;
+ }
+ avg /= jobTimings.size();
+ /* Not the best solution since we dont know exactly
+ * how much jobs are running in parallel.
+ */
+ tot = (tot / parallelJobCount) / 60;
+ est = (avg * (jobs.Stacksize() + jobs.getBusyWorker())) / 60;
+
+ return std::make_tuple(avg, tot, est);
+}
+
void UpdateGUIFrame::OnThread(wxCommandEvent& event)
{
wxString wxs;
LogType tp = RTL_DEFAULT;
static size_t counter = 0;
- bool printAllJobsDone = false;
+ static std::vector<unsigned> jobTimings;
+ unsigned avgJobTime = 0, totJobTime = 0, estTotalJobTime = 0;
+ bool allJobsDone = false;
+ JobReport *jobReport = nullptr;
/* some periodic informational output */
if ((++counter % 30) == 0) {
@@ -347,17 +375,20 @@ void UpdateGUIFrame::OnThread(wxCommandEvent& event)
switch (event.GetId()) {
case Job::eID_THREAD_JOB_DONE:
+ /* calculate job execution times (total/average/estimated) */
+ jobReport = dynamic_cast<JobReport *>(event.GetClientObject());
+ std::tie (avgJobTime, totJobTime, estTotalJobTime) = calcJobTimingsAvgTotEst(*jobs, threads.size(), *jobReport, jobTimings);
/* If more then one job was in the queue
- * inform the user about job completion.
+ * inform the user about job completion,
+ * otherwise reset completed job counter.
*/
if (jobs->Stacksize() == 0 && jobs->getBusyWorker() == 0) {
- if (jobs->getTotalJobsDone() > 1) {
- counter = 0;
- printAllJobsDone = true;
- }
+ if (jobs->getTotalJobsDone() > 1)
+ allJobsDone = true;
jobs->resetTotalJobsDone();
} else {
- SetStatusText(wxs + wxString::Format(wxT(" (jobs remaining: %u)"), jobs->Stacksize() + jobs->getBusyWorker()));
+ SetStatusText(wxString::Format(wxT("Jobs remaining: %u, estimated remaining time: %umin"),
+ jobs->Stacksize() + jobs->getBusyWorker(), estTotalJobTime));
}
break;
case Job::eID_THREAD_JOB: SetStatusText(wxs); break;
@@ -367,18 +398,25 @@ void UpdateGUIFrame::OnThread(wxCommandEvent& event)
tLog(tp, wxs);
break;
case Job::eID_THREAD_EXIT:
+ /* should only be run once per thread and only if the app exits */
SetStatusText(wxString::Format(wxT("Thread [%i]: Stopped."), event.GetInt()));
threads.remove(event.GetInt());
if (threads.empty()) { this->OnExit(event); }
break;
case Job::eID_THREAD_STARTED:
+ /* should only be run once per thread and only if the app starts */
SetStatusText(wxString::Format(wxT("Thread [%i]: Ready."), event.GetInt()));
break;
default: event.Skip();
}
- if (printAllJobsDone) {
- SetStatusText(wxT("All jobs finished."));
- tLog(RTL_GREEN, "All jobs finished.");
+ /* job queue is now empty and had more than one job */
+ if (allJobsDone) {
+ counter = 0;
+ /* we presume that threads.size() jobs ran at the same time */
+ wxs = wxString::Format(wxT("All jobs finished. Time consumption: %umin (average per device: %umin %usec)"), (unsigned)((float)totJobTime + 0.5f) /* roundup */, avgJobTime / 60, avgJobTime % 60);
+ SetStatusText(wxs);
+ tLog(RTL_GREEN, wxs);
+ jobTimings.clear();
}
}