]> git.sur5r.net Git - bacula/bacula/commitdiff
Massive bat notifier rewrite + fix seg fault + implement text input dialog
authorKern Sibbald <kern@sibbald.com>
Sat, 18 Sep 2010 13:04:54 +0000 (15:04 +0200)
committerKern Sibbald <kern@sibbald.com>
Sat, 18 Sep 2010 13:11:41 +0000 (15:11 +0200)
14 files changed:
bacula/src/console/console.c
bacula/src/dird/protos.h
bacula/src/dird/ua_input.c
bacula/src/dird/ua_tree.c
bacula/src/lib/bnet.c
bacula/src/lib/bsock.h
bacula/src/qt-console/bcomm/dircomm.cpp
bacula/src/qt-console/bcomm/dircomm.h
bacula/src/qt-console/console/console.cpp
bacula/src/qt-console/mainwin.cpp
bacula/src/qt-console/mainwin.h
bacula/src/qt-console/restore/prerestore.cpp
bacula/src/qt-console/select/select.cpp
bacula/src/qt-console/select/textinput.cpp

index 4e0e3f519ba6bd63203f52cb9c7d3b5c3252ad37..04e51abf81eed58a65228689977ad227b3cf12fe 100644 (file)
@@ -324,7 +324,7 @@ static void read_and_process_input(FILE *input, BSOCK *UA_sock)
       if (is_bnet_stop(UA_sock)) {
          break;                       /* error or term */
       } else if (stat == BNET_SIGNAL) {
-         if (UA_sock->msglen == BNET_PROMPT) {
+         if (UA_sock->msglen == BNET_SUB_PROMPT) {
             at_prompt = true;
          }
          Dmsg1(100, "Got poll %s\n", bnet_sig_to_ascii(UA_sock));
index 159d6d5352cdc39167e0461fdedb492a98db38c4..ae358fd92a4ea442bb94e0f21830f5c705c5e34e 100644 (file)
@@ -210,7 +210,7 @@ void set_pooldbr_from_poolres(POOL_DBR *pr, POOL *pool, e_pool_op op);
 int update_pool_references(JCR *jcr, B_DB *db, POOL *pool);
 
 /* ua_input.c */
-int get_cmd(UAContext *ua, const char *prompt);
+int get_cmd(UAContext *ua, const char *prompt, bool subprompt=false);
 bool get_pint(UAContext *ua, const char *prompt);
 bool get_yesno(UAContext *ua, const char *prompt);
 bool is_yesno(char *val, int *ret);
index 23a629bc5a0fc8b42c5dcea76507de74a39ac1f9..2b16f507433fc1e260febb4346fe5e8ae18faa66 100644 (file)
 
 /* Exported functions */
 
-int get_cmd(UAContext *ua, const char *prompt)
+/* 
+ * If subprompt is set, we send a BNET_SUB_PROMPT signal otherwise
+ *   send a BNET_TEXT_INPUT signal.
+ */
+int get_cmd(UAContext *ua, const char *prompt, bool subprompt)
 {
    BSOCK *sock = ua->UA_sock;
    int stat;
@@ -52,8 +56,13 @@ int get_cmd(UAContext *ua, const char *prompt)
    if (!sock || ua->batch) {          /* No UA or batch mode */
       return 0;
    }
+   if (!subprompt) {
+      sock->signal(BNET_TEXT_INPUT);
+   }
    sock->fsend("%s", prompt);
-   sock->signal(BNET_PROMPT);         /* request more input */
+   if (subprompt) {
+      sock->signal(BNET_SUB_PROMPT);
+   }
    for ( ;; ) {
       stat = sock->recv();
       if (stat == BNET_SIGNAL) {
index fa66a51f55ff8082b470550fb6a20b8c356d82ab..7d08b564106fdc2dfdcad822eaf630ad98d40b9f 100644 (file)
@@ -130,7 +130,7 @@ bool user_select_files_from_tree(TREE_CTX *tree)
    ua->send_msg(_("cwd is: %s\n"), cwd);
    for ( ;; ) {
       int found, len, i;
-      if (!get_cmd(ua, "$ ")) {
+      if (!get_cmd(ua, "$ ", true)) {
          break;
       }
       if (ua->api) user->signal(BNET_CMD_BEGIN);
index 43e9a5315ca36b776cb757eed6666687af663813..49fda5b144cbbd54312d950cd4998be342103351 100644 (file)
@@ -652,8 +652,10 @@ const char *bnet_sig_to_ascii(BSOCK * bs)
       return "BNET_HEARTBEAT";
    case BNET_HB_RESPONSE:
       return "BNET_HB_RESPONSE";
-   case BNET_PROMPT:
-      return "BNET_PROMPT";
+   case BNET_SUB_PROMPT:
+      return "BNET_SUB_PROMPT";
+   case BNET_TEXT_INPUT:
+      return "BNET_TEXT_INPUT";
    default:
       sprintf(buf, _("Unknown sig %d"), (int)bs->msglen);
       return buf;
index 430ce4035ac11c3ac42d42243ad6aa3c392b7dc5..9b9f40c4403fc5329ec4a18328ffe20331bbe23c 100644 (file)
@@ -166,7 +166,7 @@ enum {
    BNET_POLL           = -5,          /* Poll request, I'm hanging on a read */
    BNET_HEARTBEAT      = -6,          /* Heartbeat Response requested */
    BNET_HB_RESPONSE    = -7,          /* Only response permited to HB */
-   BNET_PROMPT         = -8,          /* Prompt for subcommand */
+   BNET_xxxxxxPROMPT   = -8,          /* No longer used -- Prompt for subcommand */
    BNET_BTIME          = -9,          /* Send UTC btime */
    BNET_BREAK          = -10,         /* Stop current command -- ctl-c */
    BNET_START_SELECT   = -11,         /* Start of a selection list */
@@ -184,7 +184,9 @@ enum {
    BNET_RUN_CMD        = -23,         /* Run command follows */
    BNET_YESNO          = -24,         /* Request yes no response */
    BNET_START_RTREE    = -25,         /* Start restore tree mode */
-   BNET_END_RTREE      = -26          /* End restore tree mode */ 
+   BNET_END_RTREE      = -26,         /* End restore tree mode */ 
+   BNET_SUB_PROMPT     = -27,         /* Indicate we are at a subprompt */
+   BNET_TEXT_INPUT     = -28          /* Get text input from user */
 };
 
 #define BNET_SETBUF_READ  1           /* Arg for bnet_set_buffer_size */
index 4e6e978f26729c96dc5d1e0d73fb7cded978f161..2042cee03464f6baee00f1ba9d2a5516bc34488d 100644 (file)
@@ -94,9 +94,7 @@ bool DirComm::connect_dir()
       goto bail_out;
    }
 
-   if (mainWin->m_connDebug) {
-      Pmsg2(000, "DirComm %i connecting %s\n", m_conn, m_console->m_dir->name());
-   }
+   if (mainWin->m_connDebug)Pmsg2(000, "DirComm %i connecting %s\n", m_conn, m_console->m_dir->name());
    memset(jcr, 0, sizeof(JCR));
 
    mainWin->set_statusf(_("Connecting to Director %s:%d"), m_console->m_dir->address, m_console->m_dir->DIRport);
@@ -129,8 +127,9 @@ bool DirComm::connect_dir()
       if (!cons->tls_ctx) {
          m_console->display_textf(_("Failed to initialize TLS context for Console \"%s\".\n"),
             m_console->m_dir->name());
-         if (mainWin->m_connDebug)
+         if (mainWin->m_connDebug) {
             Pmsg2(000, "DirComm %i BAILING Failed to initialize TLS context for Console %s\n", m_conn, m_console->m_dir->name());
+         }
          goto bail_out;
       }
    }
@@ -152,8 +151,9 @@ bool DirComm::connect_dir()
          m_console->display_textf(_("Failed to initialize TLS context for Director \"%s\".\n"),
             m_console->m_dir->name());
          mainWin->set_status("Connection failed");
-         if (mainWin->m_connDebug)
+         if (mainWin->m_connDebug) {
             Pmsg2(000, "DirComm %i BAILING Failed to initialize TLS context for Director %s\n", m_conn, m_console->m_dir->name());
+         }
          goto bail_out;
       }
    }
@@ -171,8 +171,9 @@ bool DirComm::connect_dir()
                           NULL, m_console->m_dir->DIRport, 0);
    if (m_sock == NULL) {
       mainWin->set_status("Connection failed");
-      if (mainWin->m_connDebug)
+      if (mainWin->m_connDebug) {
          Pmsg2(000, "DirComm %i BAILING Connection failed %s\n", m_conn, m_console->m_dir->name());
+      }
       goto bail_out;
    } else {
       /* Update page selector to green to indicate that Console is connected */
@@ -188,8 +189,9 @@ bool DirComm::connect_dir()
 
    if (!authenticate_director(jcr, m_console->m_dir, cons, buf, sizeof(buf))) {
       m_console->display_text(buf);
-      if (mainWin->m_connDebug)
+      if (mainWin->m_connDebug) {
          Pmsg2(000, "DirComm %i BAILING Connection failed %s\n", m_conn, m_console->m_dir->name());
+      }
       goto bail_out;
    }
 
@@ -206,8 +208,8 @@ bool DirComm::connect_dir()
     * Set up input notifier
     */
    m_notifier = new QSocketNotifier(m_sock->m_fd, QSocketNotifier::Read, 0);
-   QObject::connect(m_notifier, SIGNAL(activated(int)), this, SLOT(read_dir(int)));
-   m_notifier->setEnabled(false);
+   QObject::connect(m_notifier, SIGNAL(activated(int)), this, SLOT(notify_read_dir(int)));
+   m_notifier->setEnabled(true);
 
    write(".api 1");
    m_api_set = true;
@@ -341,19 +343,24 @@ int DirComm::read()
             mainWin->set_status(_("At main prompt waiting for input ..."));
          }
          break;
-      case BNET_PROMPT:
-         if (mainWin->m_commDebug) Pmsg2(000, "conn %i PROMPT m_in_select %i\n", m_conn, m_in_select);
+      case BNET_SUB_PROMPT:
+         if (mainWin->m_commDebug) Pmsg2(000, "conn %i SUB_PROMPT m_in_select=%d\n", m_conn, m_in_select);
          m_at_prompt = true;
          m_at_main_prompt = false;
          mainWin->set_status(_("At prompt waiting for input ..."));
-         /***** FIXME *****/
-         /* commented out until the prompt communication issue with the director is resolved 
-          * This is where I call a new text input dialog class to prevent the connection issues
-          * when a text input is requited.
-          *   if (!m_in_select) {
-          *      new textInputDialog(m_console, m_conn);
-          *   }
-          */
+         break;
+      case BNET_TEXT_INPUT:
+         if (mainWin->m_commDebug) Pmsg4(000, "conn %i TEXT_INPUT at_prompt=%d  m_in_select=%d notify=%d\n", 
+               m_conn, m_at_prompt, m_in_select, is_notify_enabled());
+         if (!m_in_select && is_notify_enabled()) {
+            mainWin->waitExit();
+            new textInputDialog(m_console, m_conn);
+         } else {
+            if (mainWin->m_commDebug) Pmsg0(000, "!m_in_select && is_notify_enabled\n");
+            m_at_prompt = true;
+            m_at_main_prompt = false;
+            mainWin->set_status(_("At prompt waiting for input ..."));
+         }
          break;
       case BNET_CMD_FAILED:
          if (mainWin->m_commDebug) Pmsg1(000, "CMD FAILED\n", m_conn);
@@ -413,6 +420,11 @@ int DirComm::read()
          mainWin->set_status(msg());
          break;
       }
+
+      if (!m_sock) {
+         stat = BNET_HARDEOF;
+         return stat;
+      }
       if (is_bnet_stop(m_sock)) {         /* error or term request */
          if (mainWin->m_commDebug) Pmsg1(000, "conn %i BNET STOP\n", m_conn);
          m_console->stopTimer();
@@ -436,9 +448,12 @@ int DirComm::read()
 }
 
 /* Called by signal when the Director has output for us */
-void DirComm::read_dir(int /* fd */)
+void DirComm::notify_read_dir(int /* fd */)
 {
    int stat;
+   if (!mainWin->m_notify) {
+      return;
+   }
    if (mainWin->m_commDebug) Pmsg1(000, "enter read_dir conn %i read_dir\n", m_conn);
    stat = m_sock->wait_data(0, 5000);
    if (stat > 0) {
@@ -463,24 +478,23 @@ void DirComm::read_dir(int /* fd */)
 bool DirComm::notify(bool enable) 
 { 
    bool prev_enabled = false;
+   /* Set global flag */
+   mainWin->m_notify = enable;
    if (m_notifier) {
       prev_enabled = m_notifier->isEnabled();   
-      m_notifier->setEnabled(enable);
-      if (mainWin->m_connDebug) {
-         Pmsg3(000, "conn=%i notify=%d prev=%d\n", m_conn, enable, prev_enabled);
+      if (prev_enabled != enable) {
+         m_notifier->setEnabled(enable);
       }
-   } else if (mainWin->m_connDebug)
+      if (mainWin->m_connDebug) Pmsg3(000, "conn=%i notify=%d prev=%d\n", m_conn, enable, prev_enabled);
+   } else if (mainWin->m_connDebug) {
       Pmsg2(000, "m_notifier does not exist: %i %s\n", m_conn, m_console->m_dir->name());
+   }
    return prev_enabled;
 }
 
 bool DirComm::is_notify_enabled() const
 {
-   bool enabled = false;
-   if (m_notifier) {
-      enabled = m_notifier->isEnabled();   
-   }
-   return enabled;
+   return mainWin->m_notify;
 }
 
 /*
index 8c2b9000b75130fbf6f1e1e8334e0952fc5a46d7..fbc0da61e7c52cd0fccea39f66e08f457d82a077 100644 (file)
@@ -72,7 +72,7 @@ public:
    int write(QString msg);
 
 public slots:
-   void read_dir(int fd);
+   void notify_read_dir(int fd);
 
 private:
    BSOCK *m_sock;   
index b421fc0029e8738edc99e45134aeb0e90e62bf44..dcc7d87d637db7f72d2d24c1817db0d0e5dac622 100644 (file)
@@ -97,6 +97,11 @@ void Console::poll_messages()
 {
    int conn;
 
+   /* Do not poll if notifier off */
+   if (!mainWin->m_notify) {
+      return;
+   }
+
    /*
     * Note if we call getDirComm here, we continuously consume
     *  file descriptors.
@@ -148,9 +153,7 @@ void Console::populateLists(bool /*forcenew*/)
 {
    int conn;
    if (!getDirComm(conn)) {
-      if (mainWin->m_connDebug) {
-         Pmsg0(000, "call newDirComm\n");
-      }
+      if (mainWin->m_connDebug) Pmsg0(000, "call newDirComm\n");
       if (!newDirComm(conn)) {
          Emsg1(M_ABORT, 0, "Failed to connect to %s for populateLists.\n", m_dir->name());
          return;
@@ -233,6 +236,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);
@@ -246,10 +250,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 */
 }
 
 /*
@@ -287,6 +293,7 @@ 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;
@@ -319,7 +326,7 @@ bool Console::sql_cmd(int &conn, const char *query, QStringList &results, bool d
       }
       first = false;
    }
-   if (donotify) {
+   if (donotify && prev_notify) {
       dircomm->notify(true);
    }
    discardToPrompt(conn);
@@ -402,9 +409,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();
@@ -471,19 +481,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;
 }
 
 
@@ -664,6 +671,8 @@ QString Console::returnFromPrompt(int conn)
 
    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) {
@@ -838,9 +847,7 @@ bool Console::getDirComm(int &conn)
    if (findDirComm(conn)) {
       return true;
    }
-   if (mainWin->m_connDebug) {
-      Pmsg0(000, "call newDirComm\n");
-   }
+   if (mainWin->m_connDebug) Pmsg0(000, "call newDirComm\n");
    return newDirComm(conn);
 }
 
index 15d75658251e0c57b5dd46999817ba4a7f4c87d7..7740ae96405f320a495410dc192f63c1f4807ebe 100644 (file)
@@ -97,6 +97,15 @@ MainWin::MainWin(QWidget *parent) : QMainWindow(parent)
    foreach(Console *console, m_consoleHash) {
       console->connect_dir();
    }
+   /* 
+    * Note, the notifier is now a global flag, although each notifier
+    *  can be individually turned on and off at a socket level.  Once
+    *  the notifier is turned off, we don't accept anything from anyone
+    *  this prevents unwanted messages from getting into the input
+    *  dialogs such as restore that read from the director and "know"
+    *  what to expect.
+    */
+   m_notify = true;
    m_currentConsole = (Console*)getFromHash(m_firstItem);
    QTimer::singleShot(2000, this, SLOT(popLists()));
    if (m_miscDebug) {
@@ -306,9 +315,7 @@ void MainWin::disconnectSignals()
  */
 void MainWin::waitEnter()
 {
-   if (m_waitState){ 
-      if (mainWin->m_connDebug)
-         Pmsg0(000, "Should Never Get Here DANGER DANGER, for now I'll return\n");
+   if (m_waitState || m_isClosing) { 
       return;
    }
    m_waitState = true;
@@ -327,7 +334,6 @@ void MainWin::waitExit()
    if (!m_waitState || m_isClosing) {
       return;
    }
-   m_waitState = false;
    if (mainWin->m_connDebug) Pmsg0(000, "Exiting Wait State\n");
    if (m_waitTreeItem && (m_waitTreeItem != treeWidget->currentItem())) {
       treeWidget->setCurrentItem(m_waitTreeItem);
@@ -337,6 +343,7 @@ void MainWin::waitExit()
       connectConsoleSignals();
    }
    app->restoreOverrideCursor();
+   m_waitState = false;
 }
 
 void MainWin::connectConsoleSignals()
index 6203f03b1101cc5b644d5e0cac170f4109d05851..addc501e02d80ee2466c8d512fa487ffebf7d3db 100644 (file)
@@ -105,6 +105,9 @@ public:
    bool m_openPlot;
    bool m_openDirStat;
 
+   /* Global */
+   bool m_notify;                     /* global flag to turn on/off all notifiers */
+
 public slots:
    void input_line();
    void about();
index ad56ba59475e693bde5b22f783050eaa33fda574..74d8f74f263827efe5507a1f4f21942c550644bd 100644 (file)
@@ -27,8 +27,6 @@
 */
  
 /*
- *   Version $Id$
- *
  *  preRestore -> dialog put up to determine the restore type
  *
  *   Kern Sibbald, February MMVII
@@ -140,6 +138,7 @@ void prerestorePage::okButtonPushed()
 
    this->hide();
 
+
    cmd = QString("restore");
    cmd += " fileset=\"" + filesetCombo->currentText() + "\"";
    cmd += " client=\"" + clientCombo->currentText() + "\"";
index 4932be39fc9a50f64d67695f338c85d5419649e0..ddc0438a5db1705324bf804f1a88aa34587137b7 100644 (file)
@@ -1,7 +1,7 @@
 /*
    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.
@@ -31,7 +31,6 @@
  *
  *   Kern Sibbald, March MMVII
  *
- *  $Id$
  */ 
 
 #include "bat.h"
index d96ea185407f26a77948d4404c74506a01572a4c..9c91ba8b52955f14dd9b3f97667aa97ff85eb3e0 100644 (file)
@@ -1,7 +1,7 @@
 /*
    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.
@@ -31,7 +31,6 @@
  *
  *   Kern Sibbald, March MMVII
  *
- *  $Id: select.cpp 8775 2009-04-30 16:57:18Z bartleyd2 $
  */ 
 
 #include "bat.h"
@@ -46,9 +45,11 @@ textInputDialog::textInputDialog(Console *console, int conn)
    QDateTime dt;
 
    m_console = console;
+   m_console->notify(m_conn, false);
    setupUi(this);
    setAttribute(Qt::WA_DeleteOnClose);
-   labelWidget->setText(m_console->returnFromPrompt(m_conn));
+   m_console->read(m_conn);                 /* get title */
+   labelWidget->setText(m_console->msg(m_conn));
    this->show();
 }
 
@@ -56,11 +57,10 @@ void textInputDialog::accept()
 {
    this->hide();
    m_console->write_dir(m_conn, lineEdit->text().toUtf8().data());
-   m_console->displayToPrompt(m_conn);
+   /* Do not displayToPrompt because there may be another Text Input required */
+   this->close();
    mainWin->resetFocus();
-   m_console->displayToPrompt(m_conn);
    m_console->notify(m_conn, true);
-   this->close();
 }
 
 
@@ -68,9 +68,9 @@ void textInputDialog::reject()
 {
    this->hide();
    mainWin->set_status(tr(" Canceled"));
+   m_console->write_dir(m_conn, ".");
+   this->close();
    mainWin->resetFocus();
    m_console->beginNewCommand(m_conn);
    m_console->notify(m_conn, true);
-   this->close();
 }
-