/*
Bacula® - The Network Backup Solution
- Copyright (C) 2007-2009 Free Software Foundation Europe e.V.
+ Copyright (C) 2007-2010 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.
+ 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 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.
+ 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.
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.
*/
-
+
#include "bat.h"
#include <QAbstractEventDispatcher>
#include <QMenu>
#include "run/run.h"
#include "util/fmtwidgetitem.h"
-MediaView::MediaView()
+MediaView::MediaView() : Pages()
{
setupUi(this);
m_name = tr("Media");
connect(m_pbPurge, SIGNAL(pressed()), this, SLOT(purgePushed()));
connect(m_pbDelete, SIGNAL(pressed()), this, SLOT(deletePushed()));
connect(m_pbPrune, SIGNAL(pressed()), this, SLOT(prunePushed()));
- connect(m_tableMedia, SIGNAL(itemDoubleClicked(QTableWidgetItem*)),
+ connect(m_tableMedia, SIGNAL(itemDoubleClicked(QTableWidgetItem*)),
this, SLOT(showInfoForMedia(QTableWidgetItem *)));
/* mp_treeWidget, Storage Tree Tree Widget inherited from ui_medialist.h */
QStringList sel;
QString cmd;
getSelection(sel);
-
+
for(int i=0; i<sel.count(); i++) {
cmd = sel.at(i);
new MediaEdit(mainWin->getFromHash(this), cmd);
void MediaView::purgePushed()
{
+ if (QMessageBox::warning(this, "Bat",
+ tr("Are you sure you want to purge ?? !!!.\n"
+"The Purge command will delete associated Catalog database records from Jobs and"
+" Volumes without considering the retention period. Purge works only on the"
+" Catalog database and does not affect data written to Volumes. This command can"
+" be dangerous because you can delete catalog records associated with current"
+" backups of files, and we recommend that you do not use it unless you know what"
+" you are doing.\n"
+ "Press OK to proceed with the purge operation?"),
+ QMessageBox::Ok | QMessageBox::Cancel)
+ == QMessageBox::Cancel) { return; }
+
+ QStringList lst;
+ QString cmd;
+ getSelection(lst);
+ for(int i=0; i<lst.count(); i++) {
+ cmd = "purge volume=" + lst.at(i);
+ consoleCommand(cmd);
+ }
+ populateTable();
}
bool MediaView::getSelection(QStringList &list)
{
- QList<QTableWidgetItem*> items = m_tableMedia->selectedItems();
+ int i, nb, nr_rows, row;
+ bool *tab;
QTableWidgetItem *it;
- int row;
- int nb = items.count();
- int *tab = (int *) malloc (nb * sizeof(int));
- memset(tab, 0, sizeof(int)*nb);
- for (int i = 0; i < nb; ++i) {
+ QList<QTableWidgetItem*> items = m_tableMedia->selectedItems();
+
+ /*
+ * See if anything is selected.
+ */
+ nb = items.count();
+ if (!nb) {
+ return false;
+ }
+
+ /*
+ * Create a nibble map for each row so we can see if its
+ * selected or not.
+ */
+ nr_rows = m_tableMedia->rowCount();
+ tab = (bool *)malloc (nr_rows * sizeof(bool));
+ memset(tab, 0, sizeof(bool) * nr_rows);
+
+ for (i = 0; i < nb; ++i) {
row = items[i]->row();
if (!tab[row]) {
- tab[row]=1;
+ tab[row] = true;
it = m_tableMedia->item(row, 0);
list.append(it->text());
}
}
free(tab);
+
return list.count() > 0;
}
void MediaView::deletePushed()
{
- QStringList sel;
- QString cmd;
- getSelection(sel);
-
if (QMessageBox::warning(this, "Bat",
tr("Are you sure you want to delete?? !!!.\n"
"This delete command is used to delete a Volume record and all associated catalog"
QMessageBox::Ok | QMessageBox::Cancel)
== QMessageBox::Cancel) { return; }
- cmd = "delete volume=" + sel.join(",");
- consoleCommand(cmd);
+ QStringList lst;
+ QString cmd;
+ getSelection(lst);
+ for(int i=0; i<lst.count(); i++) {
+ cmd = "delete volume=" + lst.at(i);
+ consoleCommand(cmd);
+ }
+ populateTable();
}
void MediaView::populateForm()
}
/*
- * The main meat of the class!! The function that querries the director and
+ * If chkExpired button is checked, we can remove all non Expired
+ * entries
+ */
+void MediaView::filterExipired(QStringList &list)
+{
+ utime_t t, now = time(NULL);
+ QString resultline, stat, LastWritten;
+ QStringList fieldlist;
+
+ /* We should now in advance how many rows we will have */
+ if (m_chkExpired->isChecked()) {
+ for (int i=list.size() -1; i >= 0; i--) {
+ fieldlist = list.at(i).split("\t");
+ ASSERT(fieldlist.size() != 9);
+ LastWritten = fieldlist.at(7);
+ if (LastWritten == "") {
+ list.removeAt(i);
+
+ } else {
+ stat = fieldlist.at(8);
+ t = str_to_utime(LastWritten.toAscii().data());
+ t = t + stat.toULongLong();
+ if (t > now) {
+ list.removeAt(i);
+ }
+ }
+ }
+ }
+}
+
+/*
+ * The main meat of the class!! The function that querries the director and
* creates the widgets with appropriate values.
*/
void MediaView::populateTable()
{
utime_t t;
time_t ttime;
- QString stat, LastWritten;
+ QString stat, resultline, query;
+ QString str_usage;
+ QHash<QString, float> hash_size;
+ QStringList fieldlist, results;
char buf[256];
+ float usage;
struct tm tm;
m_populated = true;
if (m_cbPool->currentText() != "") {
cmd = " Pool.Name = '" + m_cbPool->currentText() + "'";
where.append(cmd);
- }
+ }
if (m_cbStatus->currentText() != "") {
cmd = " Media.VolStatus = '" + m_cbStatus->currentText() + "'";
cmd = "";
}
- m_tableMedia->clearContents();
+ query =
+ "SELECT AVG(VolBytes) AS size, COUNT(1) as nb, "
+ "MediaType FROM Media "
+ "WHERE VolStatus IN ('Full', 'Used') "
+ "GROUP BY MediaType";
- QString query =
- "SELECT MediaId, VolumeName, InChanger, Slot, VolBytes, VolStatus, "
- "Pool.Name, "
- "MediaType, LastWritten,"
- "Media.VolRetention "
+ if (mainWin->m_sqlDebug) {
+ Pmsg1(000, "MediaView query cmd : %s\n",query.toUtf8().data());
+ }
+ if (m_console->sql_cmd(query, results)) {
+ foreach (resultline, results) {
+ fieldlist = resultline.split("\t");
+ if (fieldlist.at(1).toInt() >= 1) {
+ // MediaType
+ hash_size[fieldlist.at(2)]
+ = fieldlist.at(0).toFloat();
+ }
+ }
+ }
+
+ m_tableMedia->clearContents();
+ query =
+ "SELECT VolumeName, InChanger, "
+ "Slot, MediaType, VolStatus, VolBytes, Pool.Name, "
+ "LastWritten, Media.VolRetention "
"FROM Media JOIN Pool USING (PoolId) "
- "LEFT JOIN Location USING (LocationId) "
- + cmd +
+ "LEFT JOIN Location ON (Media.LocationId=Location.LocationId) "
+ + cmd +
" ORDER BY VolumeName LIMIT " + m_sbLimit->cleanText();
-// Pmsg1(000, "MediaView query cmd : %s\n",query.toUtf8().data());
-
- QStringList results;
+ m_tableMedia->sortByColumn(0, Qt::AscendingOrder);
+ m_tableMedia->setSortingEnabled(false); /* Don't sort during insert */
+ results.clear();
+ if (mainWin->m_sqlDebug) {
+ Pmsg1(000, "MediaView query cmd : %s\n",query.toUtf8().data());
+ }
if (m_console->sql_cmd(query, results)) {
- QString resultline;
- QStringList fieldlist;
- m_tableMedia->setRowCount(results.size());
int row=0;
+ filterExipired(results);
+ m_tableMedia->setRowCount(results.size());
+
foreach (resultline, results) { // should have only one result
+ int index = 0;
+ QString VolBytes, MediaType, LastWritten, VolStatus;
fieldlist = resultline.split("\t");
+ if (fieldlist.size() != 10) {
+ continue;
+ }
QStringListIterator fld(fieldlist);
- int index=0;
TableItemFormatter mediaitem(*m_tableMedia, row);
- fld.next(); // MediaId
-
/* VolumeName */
- mediaitem.setTextFld(index++, fld.next());
-
- /* Online */
mediaitem.setTextFld(index++, fld.next());
- fld.next(); // Slot
+
+ /* Online */
+ mediaitem.setInChanger(index++, fld.next());
+
+ /* Slot */
+ mediaitem.setNumericFld(index++, fld.next());
+
+ MediaType = fld.next();
+ VolStatus = fld.next();
/* Volume bytes */
- mediaitem.setBytesFld(index++, fld.next());
+ VolBytes = fld.next();
+ mediaitem.setBytesFld(index++, VolBytes);
/* Usage */
- mediaitem.setTextFld(index++, "NYI");
-
+ usage = 0;
+ if (hash_size.contains(MediaType) &&
+ hash_size[MediaType] != 0) {
+ usage = VolBytes.toLongLong() * 100 / hash_size[MediaType];
+ }
+ mediaitem.setPercent(index++, usage);
+
/* Volstatus */
- mediaitem.setVolStatusFld(index++, fld.next());
+ mediaitem.setVolStatusFld(index++, VolStatus);
/* Pool */
mediaitem.setTextFld(index++, fld.next());
/* MediaType */
- mediaitem.setTextFld(index++, fld.next());
+ mediaitem.setTextFld(index++, MediaType);
- /* LastWritten */
LastWritten = fld.next();
- mediaitem.setTextFld(index++, LastWritten);
+ buf[0] = 0;
+ if (LastWritten != "") {
+ stat = fld.next(); // VolUseDuration
+ t = str_to_utime(LastWritten.toAscii().data());
+ t = t + stat.toULongLong();
+ ttime = t;
+ localtime_r(&ttime, &tm);
+ strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm);
+ }
- stat = fld.next();
- t = str_to_utime(LastWritten.toAscii().data());
- t = t + stat.toULongLong();
- ttime = t;
- localtime_r(&ttime, &tm);
- strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm);
+ /* LastWritten */
+ mediaitem.setTextFld(index++, LastWritten);
+ /* When expired */
mediaitem.setTextFld(index++, buf);
-
row++;
}
}
-
m_tableMedia->resizeColumnsToContents();
m_tableMedia->resizeRowsToContents();
m_tableMedia->verticalHeader()->hide();
+ m_tableMedia->setSortingEnabled(true);
/* make read only */
m_tableMedia->setEditTriggers(QAbstractItemView::NoEditTriggers);
}
-/*
- * Called from the signal of the context sensitive menu!
- */
-void MediaView::editVolume()
-{
- MediaEdit* edit = new MediaEdit(mainWin->getFromHash(this), m_currentVolumeId);
- connect(edit, SIGNAL(destroyed()), this, SLOT(populateTable()));
-}
-
-/*
- * Called from the signal of the context sensitive menu!
- */
-void MediaView::viewVolume()
-{
- QTreeWidgetItem *parentItem = mainWin->getFromHash(this);
- MediaInfo* view = new MediaInfo(parentItem, m_currentVolumeName);
- connect(view, SIGNAL(destroyed()), this, SLOT(populateTable()));
-
-}
-
/*
* When the treeWidgetItem in the page selector tree is singleclicked, Make sure
* The tree has been populated.
populateForm();
populateTable();
}
- dockPage();
+ if (!isOnceDocked()) {
+ dockPage();
+ }
}
/*
}
}
-/*
- * Called from the signal of the context sensitive menu to delete a volume!
- */
-void MediaView::deleteVolume()
-{
- if (QMessageBox::warning(this, "Bat",
- tr("Are you sure you want to delete?? !!!.\n"
-"This delete command is used to delete a Volume record and all associated catalog"
-" records that were created. This command operates only on the Catalog"
-" database and has no effect on the actual data written to a Volume. This"
-" command can be dangerous and we strongly recommend that you do not use"
-" it unless you know what you are doing. All Jobs and all associated"
-" records (File and JobMedia) will be deleted from the catalog."
- "Press OK to proceed with delete operation.?"),
- QMessageBox::Ok | QMessageBox::Cancel)
- == QMessageBox::Cancel) { return; }
-
- QStringList lst;
- QString cmd;
- getSelection(lst);
- for(int i=0; i<lst.count(); i++) {
- cmd = "delete volume=" + lst.at(i);
- consoleCommand(cmd);
- }
- populateTable();
-}
-
-/*
- * Called from the signal of the context sensitive menu to purge!
- */
-void MediaView::purgeVolume()
-{
- if (QMessageBox::warning(this, "Bat",
- tr("Are you sure you want to purge ?? !!!.\n"
-"The Purge command will delete associated Catalog database records from Jobs and"
-" Volumes without considering the retention period. Purge works only on the"
-" Catalog database and does not affect data written to Volumes. This command can"
-" be dangerous because you can delete catalog records associated with current"
-" backups of files, and we recommend that you do not use it unless you know what"
-" you are doing.\n"
- "Press OK to proceed with the purge operation?"),
- QMessageBox::Ok | QMessageBox::Cancel)
- == QMessageBox::Cancel) { return; }
-
- QStringList lst;
- QString cmd;
- getSelection(lst);
- for(int i=0; i<lst.count(); i++) {
- cmd = "purge volume=" + lst.at(i);
- consoleCommand(cmd);
- }
- populateTable();
-}
-
-/*
- * Called from the signal of the context sensitive menu to prune!
- */
-void MediaView::pruneVolume()
-{
- new prunePage(m_currentVolumeName, "");
-}
-
// /*
// * Called from the signal of the context sensitive menu to relabel!
// */
// setConsoleCurrent();
// new relabelDialog(m_console, m_currentVolumeName);
// }
-//
+//
// /*
// * Called from the signal of the context sensitive menu to purge!
// */
// consoleCommand(cmd);
// populateTable();
// }
-//
+//
// void MediaView::allVolumes()
// {
// QString cmd = "update volume allfrompools";
// consoleCommand(cmd);
// populateTable();
// }
-//
+//
// /*
// * Called from the signal of the context sensitive menu to purge!
// */
// consoleCommand(cmd);
// populateTable();
// }
-//
+//