X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fqt-console%2Fconsole%2Fconsole.cpp;h=a183b919ecb016e340e929dc4f0950281402b397;hb=513c2c6cf9c7991273cf3330404575aafae6d8a2;hp=dacbd97e458a23d610beec609a782b6f31196554;hpb=ccf58c433cfaee0ab871933e454e44073b97dc1d;p=bacula%2Fbacula diff --git a/bacula/src/qt-console/console/console.cpp b/bacula/src/qt-console/console/console.cpp index dacbd97e45..a183b919ec 100644 --- a/bacula/src/qt-console/console/console.cpp +++ b/bacula/src/qt-console/console/console.cpp @@ -1,36 +1,25 @@ /* - 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. */ /* - * Version $Id$ - * * Console Class * - * Kern Sibbald, January MMVII + * Written by Kern Sibbald, January MMVII * */ @@ -40,15 +29,20 @@ #include "select.h" #include "run/run.h" -Console::Console(QStackedWidget *parent) +Console::Console(QTabWidget *parent) : Pages() { QFont font; + m_name = tr("Console"); m_messages_pending = false; m_parent = parent; m_closeable = false; m_console = this; m_warningPrevent = false; m_dircommCounter = 0; + + /* + * Create a connection to the Director and put it in a hash table + */ m_dircommHash.insert(m_dircommCounter, new DirComm(this, m_dircommCounter)); setupUi(this); @@ -75,7 +69,7 @@ void Console::startTimer() { m_timer = new QTimer(this); QWidget::connect(m_timer, SIGNAL(timeout()), this, SLOT(poll_messages())); - m_timer->start(mainWin->m_checkMessagesInterval*1000); + m_timer->start(mainWin->m_checkMessagesInterval*30000); } void Console::stopTimer() @@ -93,12 +87,22 @@ void Console::stopTimer() void Console::poll_messages() { int conn; - if (!availableDirComm(conn)) + + /* Do not poll if notifier off */ + if (!mainWin->m_notify) { return; - DirComm *dircomm = m_dircommHash.value(conn); + } + + /* + * Note if we call getDirComm here, we continuously consume + * file descriptors. + */ + if (!findDirComm(conn)) { /* find a free DirComm */ + return; /* try later */ + } + DirComm *dircomm = m_dircommHash.value(conn); if (mainWin->m_checkMessages && dircomm->m_at_main_prompt && hasFocus() && !mainWin->getWaitState()){ - messagesPending(true); dircomm->write(".messages"); displayToPrompt(conn); messagesPending(false); @@ -121,8 +125,9 @@ void Console::connect_dir() m_textEdit = textEdit; /* our console screen */ if (dircomm->connect_dir()) { - if (mainWin->m_connDebug) + if (mainWin->m_connDebug) { Pmsg1(000, "DirComm 0 Seems to have Connected %s\n", m_dir->name()); + } beginNewCommand(0); } mainWin->set_status(_("Connected")); @@ -134,26 +139,24 @@ void Console::connect_dir() * A function created to separate out the population of the lists * from the Console::connect_dir function */ -void Console::populateLists(bool forcenew) +void Console::populateLists(bool /*forcenew*/) { int conn; - if (forcenew) { + if (!getDirComm(conn)) { + if (mainWin->m_connDebug) Pmsg0(000, "call newDirComm\n"); if (!newDirComm(conn)) { - Pmsg1(000, "newDirComm Seems to Failed to create a connection for populateLists %s\n", m_dir->name()); - return; - } - } else { - if (!availableDirComm(conn)) { - Pmsg1(000, "availableDirComm Seems to Failed to find a connection for populateListsi %s\n", m_dir->name()); + Emsg1(M_INFO, 0, "Failed to connect to %s for populateLists.\n", m_dir->name()); return; } } populateLists(conn); + notify(conn, true); } void Console::populateLists(int conn) { job_list.clear(); + restore_list.clear(); client_list.clear(); fileset_list.clear(); messages_list.clear(); @@ -161,7 +164,10 @@ void Console::populateLists(int conn) storage_list.clear(); type_list.clear(); level_list.clear(); + volstatus_list.clear(); + mediatype_list.clear(); dir_cmd(conn, ".jobs", job_list); + dir_cmd(conn, ".jobs type=R", restore_list); dir_cmd(conn, ".clients", client_list); dir_cmd(conn, ".filesets", fileset_list); dir_cmd(conn, ".msgs", messages_list); @@ -169,6 +175,9 @@ void Console::populateLists(int conn) dir_cmd(conn, ".storage", storage_list); dir_cmd(conn, ".types", type_list); dir_cmd(conn, ".levels", level_list); + dir_cmd(conn, ".volstatus", volstatus_list); + dir_cmd(conn, ".mediatypes", mediatype_list); + dir_cmd(conn, ".locations", location_list); if (mainWin->m_connDebug) { QString dbgmsg = QString("jobs=%1 clients=%2 filesets=%3 msgs=%4 pools=%5 storage=%6 types=%7 levels=%8 conn=%9 %10\n") @@ -202,11 +211,11 @@ bool Console::dir_cmd(QString &cmd, QStringList &results) bool Console::dir_cmd(const char *cmd, QStringList &results) { int conn; - if (availableDirComm(conn)) { + if (getDirComm(conn)) { dir_cmd(conn, cmd, results); return true; } else { - Pmsg1(000, "dir_cmd Seems to Failed to find a connection %s\n", m_dir->name()); + Pmsg1(000, "dir_cmd failed to connect to %s\n", m_dir->name()); return false; } } @@ -220,12 +229,15 @@ bool Console::dir_cmd(int conn, const char *cmd, QStringList &results) mainWin->waitEnter(); DirComm *dircomm = m_dircommHash.value(conn); int stat; + bool prev_notify = is_notify_enabled(conn); if (mainWin->m_connDebug) { QString dbgmsg = QString("dir_cmd conn %1 %2 %3\n").arg(conn).arg(m_dir->name()).arg(cmd); Pmsg1(000, "%s", dbgmsg.toUtf8().data()); } - notify(conn, false); + if (prev_notify) { + notify(conn, false); + } dircomm->write(cmd); while ((stat = dircomm->read()) > 0 && dircomm->is_in_command()) { if (mainWin->m_displayAll) display_text(dircomm->msg()); @@ -233,10 +245,12 @@ bool Console::dir_cmd(int conn, const char *cmd, QStringList &results) results << dircomm->msg(); } if (stat > 0 && mainWin->m_displayAll) display_text(dircomm->msg()); - notify(conn, true); + if (prev_notify) { + notify(conn, true); /* turn it back on */ + } discardToPrompt(conn); mainWin->waitExit(); - return true; /* ***FIXME*** return any command error */ + return true; /* ***FIXME*** return any command error */ } /* @@ -250,16 +264,18 @@ bool Console::sql_cmd(int &conn, QString &query, QStringList &results) bool Console::sql_cmd(QString &query, QStringList &results) { int conn; - if (!availableDirComm(conn)) + if (!getDirComm(conn)) { return false; + } return sql_cmd(conn, query.toUtf8().data(), results, true); } bool Console::sql_cmd(const char *query, QStringList &results) { int conn; - if (!availableDirComm(conn)) + if (!getDirComm(conn)) { return false; + } return sql_cmd(conn, query, results, true); } @@ -272,15 +288,16 @@ bool Console::sql_cmd(int &conn, const char *query, QStringList &results, bool d DirComm *dircomm = m_dircommHash.value(conn); int stat; POOL_MEM cmd(PM_MESSAGE); + bool prev_notify = is_notify_enabled(conn); if (!is_connectedGui()) { return false; } - if (mainWin->m_connDebug) - Pmsg2(000, "sql_cmd conn %i %s\n", conn, query); - if (donotify) + if (mainWin->m_connDebug) Pmsg2(000, "sql_cmd conn %i %s\n", conn, query); + if (donotify) { dircomm->notify(false); + } mainWin->waitEnter(); pm_strcpy(cmd, ".sql query=\""); @@ -299,15 +316,20 @@ bool Console::sql_cmd(int &conn, const char *query, QStringList &results, bool d QString dum = dircomm->msg(); if ((dum.left(6) == "*None*")) doappend = false; } - if (doappend) + if (doappend) { results << dircomm->msg(); + } first = false; } - if (donotify) + if (donotify && prev_notify) { dircomm->notify(true); + } discardToPrompt(conn); mainWin->waitExit(); - return true; /* ***FIXME*** return any command error */ + if (donotify && prev_notify) { + dircomm->notify(true); + } + return !mainWin->isClosing(); /* return false if closing */ } /* @@ -317,16 +339,18 @@ bool Console::sql_cmd(int &conn, const char *query, QStringList &results, bool d int Console::write_dir(const char *msg) { int conn; - if (availableDirComm(conn)) + if (getDirComm(conn)) { write_dir(conn, msg); + } return conn; } int Console::write_dir(const char *msg, bool dowait) { int conn; - if (availableDirComm(conn)) + if (getDirComm(conn)) { write_dir(conn, msg, dowait); + } return conn; } @@ -366,12 +390,13 @@ void Console::write_dir(int conn, const char *msg, bool dowait) bool Console::get_job_defaults(struct job_defaults &job_defs) { int conn; + getDirComm(conn); return get_job_defaults(conn, job_defs, true); } bool Console::get_job_defaults(int &conn, struct job_defaults &job_defs) { - return get_job_defaults(conn, job_defs, false); + return get_job_defaults(conn, job_defs, true); } /* @@ -383,16 +408,21 @@ bool Console::get_job_defaults(int &conn, struct job_defaults &job_defs, bool do QString scmd; int stat; char *def; + bool prev_notify = is_notify_enabled(conn); + bool rtn = false; + DirComm *dircomm = m_dircommHash.value(conn); - if (donotify) - conn = notifyOff(); + if (donotify) { + dircomm->notify(false); + } beginNewCommand(conn); - DirComm *dircomm = m_dircommHash.value(conn); bool prevWaitState = mainWin->getWaitState(); - if (!prevWaitState) + if (!prevWaitState) { mainWin->waitEnter(); - if (mainWin->m_connDebug) + } + if (mainWin->m_connDebug) { Pmsg2(000, "job_defaults conn %i %s\n", conn, m_dir->name()); + } scmd = QString(".defaults job=\"%1\"").arg(job_defs.job_name); dircomm->write(scmd); while ((stat = dircomm->read()) > 0) { @@ -452,19 +482,16 @@ bool Console::get_job_defaults(int &conn, struct job_defaults &job_defs, bool do continue; } } - - if (donotify) - notify(conn, true); - if (!prevWaitState) - mainWin->waitExit(); - return true; - + rtn = true; + /* Fall through wanted */ bail_out: - if (donotify) + if (donotify && prev_notify) { notify(conn, true); - if (!prevWaitState) + } + if (!prevWaitState) { mainWin->waitExit(); - return false; + } + return rtn; } @@ -546,30 +573,38 @@ void Console::display_textf(const char *fmt, ...) { va_list arg_ptr; char buf[1000]; - int len; va_start(arg_ptr, fmt); - len = bvsnprintf(buf, sizeof(buf), fmt, arg_ptr); + bvsnprintf(buf, sizeof(buf), fmt, arg_ptr); va_end(arg_ptr); display_text(buf); } void Console::display_text(const QString buf) { - m_cursor->insertText(buf); - update_cursor(); + if (mainWin->isClosing()) return; + if (buf.size() != 0) { + m_cursor->insertText(buf); + update_cursor(); + } } void Console::display_text(const char *buf) { - m_cursor->insertText(buf); - update_cursor(); + if (mainWin->isClosing()) return; + if (*buf != 0) { + m_cursor->insertText(buf); + update_cursor(); + } } void Console::display_html(const QString buf) { - m_cursor->insertHtml(buf); - update_cursor(); + if (mainWin->isClosing()) return; + if (buf.size() != 0) { + m_cursor->insertHtml(buf); + update_cursor(); + } } /* Position cursor to end of screen */ @@ -583,17 +618,20 @@ void Console::beginNewCommand(int conn) { DirComm *dircomm = m_dircommHash.value(conn); + if (dircomm->m_at_main_prompt) { + return; + } for (int i=0; i < 3; i++) { dircomm->write("."); while (dircomm->read() > 0) { - Pmsg2(000, "begin new command loop %i %s\n", i, m_dir->name()); + if (mainWin->m_commDebug) Pmsg2(000, "begin new command loop %i %s\n", i, m_dir->name()); if (mainWin->m_displayAll) display_text(dircomm->msg()); } if (dircomm->m_at_main_prompt) { break; } } - display_text("\n"); + //display_text("\n"); } void Console::displayToPrompt(int conn) @@ -633,7 +671,28 @@ void Console::discardToPrompt(int conn) } } } - if (mainWin->m_commDebug) Pmsg2(000, "endDiscardToPrompt=%d %s\n", stat, m_dir->name()); + if (mainWin->m_commDebug) { + Pmsg2(000, "endDiscardToPrompt conn=%i %s\n", conn, m_dir->name()); + } +} + +QString Console::returnFromPrompt(int conn) +{ + DirComm *dircomm = m_dircommHash.value(conn); + QString text(""); + + int stat = 0; + text = ""; + dircomm->read(); + text += dircomm->msg(); + if (mainWin->m_commDebug) Pmsg1(000, "returnFromPrompt %s\n", m_dir->name()); + while (!dircomm->m_at_prompt) { + if ((stat=dircomm->read()) > 0) { + text += dircomm->msg(); + } + } + if (mainWin->m_commDebug) Pmsg2(000, "endreturnFromPrompt=%d %s\n", stat, m_dir->name()); + return text; } /* @@ -647,12 +706,13 @@ void Console::discardToPrompt(int conn) * m_console->notifiy(false); */ -/* dual purpose function to turn notify off and return an available connection */ +/* dual purpose function to turn notify off and return a connection */ int Console::notifyOff() { int conn = 0; - if (availableDirComm(conn)) + if (getDirComm(conn)) { notify(conn, false); + } return conn; } @@ -660,14 +720,22 @@ int Console::notifyOff() bool Console::notify(int conn, bool enable) { DirComm *dircomm = m_dircommHash.value(conn); - return dircomm->notify(enable); + if (dircomm) { + return dircomm->notify(enable); + } else { + return false; + } } /* knowing a connection, return notify state */ bool Console::is_notify_enabled(int conn) const { DirComm *dircomm = m_dircommHash.value(conn); - return dircomm->is_notify_enabled(); + if (dircomm) { + return dircomm->is_notify_enabled(); + } else { + return false; + } } void Console::setDirectorTreeItem(QTreeWidgetItem *item) @@ -706,7 +774,7 @@ void Console::consoleReload() * This may be rendered not needed if the multiple connections feature gets working */ bool Console::hasFocus() { - if (mainWin->stackedWidget->currentIndex() == mainWin->stackedWidget->indexOf(this)) + if (mainWin->tabWidget->currentIndex() == mainWin->tabWidget->indexOf(this)) return true; else return false; @@ -792,38 +860,42 @@ bool Console::is_connected(int conn) } /* - * Need an available connection. Check existing connections or create one + * Need a connection. Check existing connections or create one */ -bool Console::availableDirComm(int &conn) +bool Console::getDirComm(int &conn) { - QHash::const_iterator iter = m_dircommHash.constBegin(); - while (iter != m_dircommHash.constEnd()) { - DirComm *dircomm = iter.value(); - if (dircomm->m_at_prompt && dircomm->m_at_main_prompt && dircomm->is_notify_enabled()) { - conn = dircomm->m_conn; - return true; - } - ++iter; - } - if (newDirComm(conn)) + if (findDirComm(conn)) { return true; - else - return false; + } + if (mainWin->m_connDebug) Pmsg0(000, "call newDirComm\n"); + return newDirComm(conn); } /* - * Need current connection. + * Try to find a free (unused but established) connection + * KES: Note, I think there is a problem here because for + * some reason, the notifier is often turned off on file + * descriptors that seem to me to be available. That means + * that we do not use a free descriptor and thus we will create + * a new connection that is maybe not necessary. Someone needs + * to look into whether or not notify() is correctly turned on + * when we are back at the command prompt and idle. + * */ -bool Console::currentDirComm(int &conn) +bool Console::findDirComm(int &conn) { QHash::const_iterator iter = m_dircommHash.constBegin(); while (iter != m_dircommHash.constEnd()) { DirComm *dircomm = iter.value(); - if (dircomm->m_at_prompt && !dircomm->m_at_main_prompt && dircomm->is_notify_enabled()) { + if (dircomm->m_at_prompt && dircomm->m_at_main_prompt && dircomm->is_notify_enabled()) { conn = dircomm->m_conn; return true; } + if (mainWin->m_connDebug) { + Pmsg4(000, "currentDirComm=%d at_prompt=%d at_main=%d && notify=%d\n", + dircomm->m_conn, dircomm->m_at_prompt, dircomm->m_at_main_prompt, dircomm->is_notify_enabled()); + } ++iter; } return false; @@ -834,18 +906,26 @@ bool Console::currentDirComm(int &conn) */ bool Console::newDirComm(int &conn) { - m_dircommCounter += 1; - conn = m_dircommCounter; - if (mainWin->m_connDebug) - Pmsg2(000, "DirComm %i About to Create and Connect %s\n", m_dircommCounter, m_dir->name()); + m_dircommCounter++; + if (mainWin->m_connDebug) { + Pmsg2(000, "newDirComm=%i to: %s\n", m_dircommCounter, m_dir->name()); + } DirComm *dircomm = new DirComm(this, m_dircommCounter); m_dircommHash.insert(m_dircommCounter, dircomm); bool success = dircomm->connect_dir(); if (mainWin->m_connDebug) { - if (success) - Pmsg2(000, "DirComm %i Connected %s\n", conn, m_dir->name()); - else - Pmsg2(000, "DirComm %i NOT Connected %s\n", conn, m_dir->name()); + if (success) { + Pmsg2(000, "newDirComm=%i Connected %s\n", m_dircommCounter, m_dir->name()); + } else { + Emsg2(M_ERROR, 0, "DirComm=%i. Unable to connect to %s\n", + m_dircommCounter, m_dir->name()); + } } + if (!success) { + m_dircommHash.remove(m_dircommCounter); + delete dircomm; + m_dircommCounter--; + } + conn = m_dircommCounter; return success; }