/*
- Bacula® - The Network Backup Solution
-
- Copyright (C) 2007-2009 Free Software Foundation Europe e.V.
-
- The main author of Bacula is Kern Sibbald, with contributions from
- many others, a complete list can be found in the file AUTHORS.
- This program is Free Software; you can redistribute it and/or
- modify it under the terms of version two of the GNU General Public
- License as published by the Free Software Foundation and included
- in the file LICENSE.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
- Bacula® is a registered trademark of Kern Sibbald.
- The licensor of Bacula is the Free Software Foundation Europe
- (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
- Switzerland, email:ftf@fsfeurope.org.
+ Bacula(R) - The Network Backup Solution
+
+ Copyright (C) 2000-2016 Kern Sibbald
+
+ The original author of Bacula is Kern Sibbald, with contributions
+ from many others, a complete list can be found in the file AUTHORS.
+
+ You may use this file and others of this release according to the
+ license defined in the LICENSE file, which includes the Affero General
+ Public License, v3.0 ("AGPLv3") and some additional permissions and
+ terms pursuant to its AGPLv3 Section 7.
+
+ This notice must be preserved when any source code is
+ conveyed and/or propagated.
+
+ Bacula(R) is a registered trademark of Kern Sibbald.
*/
#include "bat.h"
#include "job.h"
#include "util/fmtwidgetitem.h"
#include "mediainfo/mediainfo.h"
+#include "run/run.h"
-Job::Job(QString &jobId, QTreeWidgetItem *parentTreeWidgetItem)
+Job::Job(QString &jobId, QTreeWidgetItem *parentTreeWidgetItem) : Pages()
{
setupUi(this);
- m_closeable = true;
pgInitialize(tr("Job"), parentTreeWidgetItem);
QTreeWidgetItem* thisitem = mainWin->getFromHash(this);
thisitem->setIcon(0,QIcon(QString::fromUtf8(":images/joblog.png")));
m_cursor = new QTextCursor(textJobLog->document());
+ m_bwlimit = 0;
m_jobId = jobId;
+ m_timer = NULL;
getFont();
connect(pbRefresh, SIGNAL(clicked()), this, SLOT(populateAll()));
connect(pbDelete, SIGNAL(clicked()), this, SLOT(deleteJob()));
+ connect(pbCancel, SIGNAL(clicked()), this, SLOT(cancelJob()));
+ connect(pbRun, SIGNAL(clicked()), this, SLOT(rerun()));
connect(list_Volume, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(showInfoVolume(QListWidgetItem *)));
+ connect(spin_Bwlimit, SIGNAL(valueChanged(int)), this, SLOT(storeBwLimit(int)));
populateAll();
dockPage();
setCurrent();
}
+void Job::rerun()
+{
+ new runPage(label_Name->text(),
+ label_Level->text(),
+ label_Pool->text(),
+ QString(""), // storage
+ label_Client->text(),
+ label_FileSet->text());
+}
+
void Job::showInfoVolume(QListWidgetItem *item)
{
QString s= item->text();
closeStackPage();
}
+void Job::cancelJob()
+{
+ if (QMessageBox::warning(this, "Bat",
+ tr("Are you sure you want to cancel this job?"),
+ QMessageBox::Ok | QMessageBox::Cancel)
+ == QMessageBox::Cancel) { return; }
+
+ QString cmd("cancel jobid=");
+ cmd += m_jobId;
+ consoleCommand(cmd, false);
+}
+
void Job::getFont()
{
QFont font = textJobLog->font();
/*
* Populate the text in the window
+ * TODO: Just append new text instead of clearing the window
*/
void Job::populateText()
{
}
+void Job::storeBwLimit(int val)
+{
+ m_bwlimit = val;
+}
+
+void Job::updateRunInfo()
+{
+ QString cmd;
+ QStringList results;
+ QStringList lst;
+ bool parseit=false;
+
+#ifdef xxx
+ /* This doesn't seem like the right thing to do */
+ if (m_bwlimit >= 100) {
+ cmd = QString("setbandwidth limit=" + QString::number(m_bwlimit)
+ + " jobid=" + m_jobId);
+ m_console->dir_cmd(cmd, results);
+ results.clear();
+ m_bwlimit = 0;
+ }
+#endif
+
+ cmd = QString(".status client=\"" + m_client + "\" running");
+/*
+ * JobId 5 Job backup.2010-12-21_09.28.17_03 is running.
+ * VSS Full Backup Job started: 21-Dec-10 09:28
+ * Files=4 Bytes=610,976 Bytes/sec=87,282 Errors=0
+ * Files Examined=4
+ * Processing file: /tmp/regress/build/po/de.po
+ * SDReadSeqNo=5 fd=5
+ *
+ * Or
+ * JobId=5
+ * Job=backup.2010-12-21_09.28.17_03
+ * VSS=1
+ * Files=4
+ * Bytes=610976
+ *
+ */
+ QRegExp jobline("(JobId) (\\d+) Job ");
+ QRegExp itemline("([\\w /]+)[:=]\\s*(.+)");
+ QRegExp filesline("Files: Examined=([\\d,]+) Backed up=([\\d,])");
+ QRegExp oldline("Files=([\\d,]+) Bytes=([\\d,]+) Bytes/sec=([\\d,]+) Errors=([\\d,]+)");
+ QRegExp restoreline("Files: Restored=([\\d,]+) Expected=([\\d,]+) Completed=([\\d,]+)%");
+ QRegExp restoreline2("Files Examined=([\\d,]+) Expected Files=([\\d,]+) Percent Complete=([\\d,]+)");
+
+ QString com(",");
+ QString empty("");
+
+ if (m_console->dir_cmd(cmd, results)) {
+ foreach (QString mline, results) {
+ foreach (QString line, mline.split("\n")) {
+ line = line.trimmed();
+ if (oldline.indexIn(line) >= 0) {
+ if (parseit) {
+ lst = oldline.capturedTexts();
+ label_JobErrors->setText(lst[4]);
+ label_Speed->setText(convertBytesSI(lst[3].replace(com, empty).toULongLong())+"/s");
+ label_JobFiles->setText(lst[1]);
+ label_JobBytes->setText(convertBytesSI(lst[2].replace(com, empty).toULongLong()));
+ }
+ continue;
+
+ } else if (filesline.indexIn(line) >= 0) {
+ if (parseit) {
+ lst = filesline.capturedTexts(); // Will also catch Backed up
+ label_FilesExamined->setText(lst[1]);
+ }
+ continue;
+
+// TODO: Need to be fixed
+// } else if (restoreline2.indexIn(line) >= 0) {
+// if (parseit) {
+// lst = filesline.capturedTexts();
+// label_FilesExamined->setText(lst[1]); // Can also handle Expected and Completed
+// }
+// continue;
+
+ } else if (jobline.indexIn(line) >= 0) {
+ lst = jobline.capturedTexts();
+ lst.removeFirst();
+
+ } else if (itemline.indexIn(line) >= 0) {
+ lst = itemline.capturedTexts();
+ lst.removeFirst();
+
+ } else {
+ if (mainWin->m_miscDebug)
+ Pmsg1(0, "bad line=%s\n", line.toUtf8().data());
+ continue;
+ }
+ if (lst.count() < 2) {
+ if (mainWin->m_miscDebug)
+ Pmsg2(0, "bad line=%s count=%d\n", line.toUtf8().data(), lst.count());
+ }
+ if (lst[0] == "JobId") {
+ if (lst[1] == m_jobId) {
+ parseit = true;
+ } else {
+ parseit = false;
+ }
+ }
+ if (!parseit) {
+ continue;
+ }
+
+// } else if (lst[0] == "Job") {
+// grpRun->setTitle(lst[1]);
+
+//
+// } else if (lst[0] == "VSS") {
+
+// } else if (lst[0] == "Level") {
+// Info->setText(lst[1]);
+//
+// } else if (lst[0] == "JobType" || lst[0] == "Type") {
+//
+// } else if (lst[0] == "JobStarted" || lst[0] == "StartTime") {
+// Started->setText(lst[1]);
+
+#ifdef xxx
+ if (lst[0] == "Bwlimit") {
+ int val = lst[1].toInt();
+ if (val > 0) {
+ chk_Bwlimit->setChecked(true);
+ spin_Bwlimit->setEnabled(true);
+ spin_Bwlimit->setValue(lst[1].toInt()/1024);
+ } else {
+ chk_Bwlimit->setEnabled(false);
+ spin_Bwlimit->setEnabled(false);
+ spin_Bwlimit->setValue(0);
+ }
+#endif
+
+ if (lst[0] == "Errors") {
+ label_JobErrors->setText(lst[1]);
+
+ } else if (lst[0] == "Bytes/sec") {
+ label_Speed->setText(convertBytesSI(lst[1].toULongLong())+"/s");
+
+ } else if (lst[0] == "Files" || lst[0] == "JobFiles") {
+ label_JobFiles->setText(lst[1]);
+
+ } else if (lst[0] == "Bytes" || lst[0] == "JobBytes") {
+ label_JobBytes->setText(convertBytesSI(lst[1].toULongLong()));
+
+ } else if (lst[0] == "Examined") {
+ label_FilesExamined->setText(lst[1]);
+
+ } else if (lst[0] == "Files Examined") {
+ label_FilesExamined->setText(lst[1]);
+
+ } else if (lst[0] == "Processing file") {
+ label_CurrentFile->setText(lst[1]);
+ }
+ }
+ }
+ }
+}
+
/*
* Populate the text in the window
*/
QString stat, err;
char buf[256];
QString query =
- "SELECT JobId, Job.Name, Level, Client.Name, Pool.Name, FileSet, SchedTime, StartTime, EndTime, "
- "EndTime - StartTime AS Duration, JobBytes, JobFiles, JobErrors, JobStatus, PurgedFiles "
- "FROM Job JOIN Client USING (ClientId) LEFT JOIN Pool USING (PoolId) "
- "LEFT JOIN FileSet USING (FileSetId)"
+ "SELECT JobId, Job.Name, Level, Client.Name, Pool.Name, FileSet,"
+ "SchedTime, StartTime, EndTime, EndTime-StartTime AS Duration, "
+ "JobBytes, JobFiles, JobErrors, JobStatus, PurgedFiles "
+ "FROM Job JOIN Client USING (ClientId) "
+ "LEFT JOIN Pool ON (Job.PoolId = Pool.PoolId) "
+ "LEFT JOIN FileSet ON (Job.FileSetId = FileSet.FileSetId)"
"WHERE JobId=" + m_jobId;
QStringList results;
if (m_console->sql_cmd(query, results)) {
- QString resultline;
+ QString resultline, duration;
QStringList fieldlist;
foreach (resultline, results) { // should have only one result
fieldlist = resultline.split("\t");
+ if (fieldlist.size() != 15) {
+ Pmsg1(000, "Unexpected line %s", resultline.toUtf8().data());
+ continue;
+ }
QStringListIterator fld(fieldlist);
label_JobId->setText(fld.next());
label_Name->setText(fld.next());
- label_Level->setText(job_level_to_str(fld.next()[0].toAscii()));
+ label_Level->setText(job_level_to_str(fld.next()[0].toLatin1()));
- label_Client->setText(fld.next());
+ m_client = fld.next();
+ label_Client->setText(m_client);
label_Pool->setText(fld.next());
label_FileSet->setText(fld.next());
label_SchedTime->setText(fld.next());
label_StartTime->setText(fld.next());
label_EndTime->setText(fld.next());
- label_Duration->setText(fld.next());
+ duration = fld.next();
+ /*
+ * Note: if we have a negative duration, it is because the EndTime
+ * is zero (i.e. the Job is still running). We should use
+ * duration = StartTime - current_time
+ */
+ if (duration.left(1) == "-") {
+ duration = "0.0";
+ }
+ label_Duration->setText(duration);
label_JobBytes->setText(convertBytesSI(fld.next().toULongLong()));
label_JobFiles->setText(fld.next());
err = fld.next();
label_JobErrors->setText(err);
- stat=fld.next();
+ stat = fld.next();
if (stat == "T" && err.toInt() > 0) {
stat = "W";
}
+ if (stat == "R") {
+ pbDelete->setVisible(false);
+ pbCancel->setVisible(true);
+ grpRun->setVisible(true);
+ if (!m_timer) {
+ m_timer = new QTimer(this);
+ connect(m_timer, SIGNAL(timeout()), this, SLOT(populateAll()));
+ m_timer->start(30000);
+ }
+ updateRunInfo();
+ } else {
+ pbDelete->setVisible(true);
+ pbCancel->setVisible(false);
+ grpRun->setVisible(false);
+ if (m_timer) {
+ m_timer->stop();
+ delete m_timer;
+ m_timer = NULL;
+ }
+ }
label_JobStatus->setPixmap(QPixmap(":/images/" + stat + ".png"));
- jobstatus_to_ascii_gui(stat[0].toAscii(), buf, sizeof(buf));
+ jobstatus_to_ascii_gui(stat[0].toLatin1(), buf, sizeof(buf));
stat = buf;
label_JobStatus->setToolTip(stat);