X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fqt-console%2Fconsole%2Fconsole.cpp;h=81fce7c02c75e89a684cce319c0567c9e966ff33;hb=e189e1ee42e3398596f4fa463bb1adc66d2cee6a;hp=25a5b1305f8ad730c97b44572043cf713af7ef84;hpb=263987014ca29ee85fd605529db7b3cd4ca05871;p=bacula%2Fbacula diff --git a/bacula/src/qt-console/console/console.cpp b/bacula/src/qt-console/console/console.cpp index 25a5b1305f..81fce7c02c 100644 --- a/bacula/src/qt-console/console/console.cpp +++ b/bacula/src/qt-console/console/console.cpp @@ -1,12 +1,12 @@ /* 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 + modify it under the terms of version three of the GNU Affero General Public License as published by the Free Software Foundation and included in the file LICENSE. @@ -15,7 +15,7 @@ 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 + You should have received a copy of the GNU Affero 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. @@ -26,8 +26,6 @@ Switzerland, email:ftf@fsfeurope.org. */ /* - * Version $Id$ - * * Console Class * * Kern Sibbald, January MMVII @@ -40,14 +38,20 @@ #include "select.h" #include "run/run.h" -Console::Console(QStackedWidget *parent) +Console::Console(QTabWidget *parent) { 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); @@ -92,11 +96,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); + } - if (mainWin->m_checkMessages && dircomm->m_at_main_prompt && hasFocus()){ + /* + * 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); @@ -120,8 +135,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")); @@ -133,17 +149,13 @@ 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_ABORT, 0, "Failed to connect to %s for populateLists.\n", m_dir->name()); return; } } @@ -153,15 +165,18 @@ void Console::populateLists(bool forcenew) void Console::populateLists(int conn) { job_list.clear(); + restore_list.clear(); client_list.clear(); fileset_list.clear(); - fileset_list.clear(); messages_list.clear(); pool_list.clear(); 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 +184,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") @@ -177,6 +195,14 @@ void Console::populateLists(int conn) .arg(conn).arg(m_dir->name()); Pmsg1(000, "%s", dbgmsg.toUtf8().data()); } + job_list.sort(); + client_list.sort(); + fileset_list.sort(); + messages_list.sort(); + pool_list.sort(); + storage_list.sort(); + type_list.sort(); + level_list.sort(); } /* @@ -194,11 +220,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; } } @@ -212,6 +238,7 @@ bool Console::dir_cmd(int conn, const char *cmd, QStringList &results) mainWin->waitEnter(); DirComm *dircomm = m_dircommHash.value(conn); int stat; + bool prev_notify = mainWin->m_notify; if (mainWin->m_connDebug) { QString dbgmsg = QString("dir_cmd conn %1 %2 %3\n").arg(conn).arg(m_dir->name()).arg(cmd); @@ -225,10 +252,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 */ } /* @@ -242,16 +271,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); } @@ -264,15 +295,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 = mainWin->m_notify; 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=\""); @@ -291,36 +323,60 @@ 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 */ + return !mainWin->isClosing(); /* return false if closing */ } -/* Send a command to the Director */ +/* + * Overloads for + * Sending a command to the Director + */ 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 (getDirComm(conn)) { + write_dir(conn, msg, dowait); + } return conn; } -/* Send a command to the Director */ void Console::write_dir(int conn, const char *msg) +{ + write_dir(conn, msg, true); +} + +/* + * Send a command to the Director + */ +void Console::write_dir(int conn, const char *msg, bool dowait) { DirComm *dircomm = m_dircommHash.value(conn); if (dircomm->m_sock) { mainWin->set_status(_("Processing command ...")); - mainWin->waitEnter(); + if (dowait) + mainWin->waitEnter(); dircomm->write(msg); - mainWin->waitExit(); + if (dowait) + mainWin->waitExit(); } else { mainWin->set_status( tr(" Director not connected. Click on connect button.")); mainWin->actionConnect->setIcon(QIcon(":images/disconnected.png")); @@ -355,9 +411,12 @@ bool Console::get_job_defaults(int &conn, struct job_defaults &job_defs, bool do QString scmd; int stat; char *def; + bool prev_notify = mainWin->m_notify; + bool rtn = false; - if (donotify) + if (donotify) { conn = notifyOff(); + } beginNewCommand(conn); DirComm *dircomm = m_dircommHash.value(conn); bool prevWaitState = mainWin->getWaitState(); @@ -424,19 +483,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; } @@ -547,7 +603,6 @@ void Console::display_html(const QString buf) /* Position cursor to end of screen */ void Console::update_cursor() { -// QApplication::restoreOverrideCursor(); m_textEdit->moveCursor(QTextCursor::End); m_textEdit->ensureCursorVisible(); } @@ -600,29 +655,54 @@ void Console::discardToPrompt(int conn) displayToPrompt(conn); } else { while (!dircomm->m_at_prompt) { - stat=dircomm->read(); + stat = dircomm->read(); + if (stat < 0) { + break; + } + } + } + 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, "endDiscardToPrompt=%d %s\n", stat, m_dir->name()); + if (mainWin->m_commDebug) Pmsg2(000, "endreturnFromPrompt=%d %s\n", stat, m_dir->name()); + return text; } /* * When the notifier is enabled, read_dir() will automatically be * called by the Qt event loop when ever there is any output - * from the Directory, and read_dir() will then display it on + * from the Director, and read_dir() will then display it on * the console. * * When we are in a bat dialog, we want to control *all* output - * from the Directory, so we set notify to off. + * from the Director, so we set notify to off. * 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; } @@ -676,7 +756,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; @@ -762,10 +842,32 @@ 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) { + if (findDirComm(conn)) { + return true; + } + if (mainWin->m_connDebug) Pmsg0(000, "call newDirComm\n"); + return newDirComm(conn); +} + + +/* + * 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::findDirComm(int &conn) +{ + int i = 1; QHash::const_iterator iter = m_dircommHash.constBegin(); while (iter != m_dircommHash.constEnd()) { DirComm *dircomm = iter.value(); @@ -773,12 +875,14 @@ bool Console::availableDirComm(int &conn) conn = dircomm->m_conn; return true; } + if (mainWin->m_connDebug) { + Pmsg4(000, "currentDirComm=%d at_prompt=%d at_main=%d && notify=%d\n", + i, dircomm->m_at_prompt, dircomm->m_at_main_prompt, dircomm->is_notify_enabled()); + i++; + } ++iter; } - if (newDirComm(conn)) - return true; - else - return false; + return false; } /* @@ -786,18 +890,26 @@ bool Console::availableDirComm(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; }