]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/qt-console/console/console.cpp
kes More bat implementation.
[bacula/bacula] / bacula / src / qt-console / console / console.cpp
index 9ff33183b978324c5b6312510a495c9aacf8caa5..b0bde34df22f1b80cdcf558e37aec1eb4a9e5b4d 100644 (file)
@@ -1,7 +1,7 @@
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
+   Copyright (C) 2007-2007 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.
    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
    Switzerland, email:ftf@fsfeurope.org.
 */
 /*
+ *   Version $Id$
+ *
  *  Console Class
  *
- *   Kern Sibbald, January MMVI
+ *   Kern Sibbald, January MMVII
  *
  */ 
 
 #include <QAbstractEventDispatcher>
 #include "bat.h"
 #include "console.h"
-#include "restore.h"
 
 Console::Console(QStackedWidget *parent)
 {
@@ -52,16 +52,16 @@ Console::Console(QStackedWidget *parent)
    m_cursor = new QTextCursor(m_textEdit->document());
    mainWin->actionConnect->setIcon(QIcon(QString::fromUtf8("images/disconnected.png")));
 
-   bRestore *restore = new bRestore(parent);
-   restore->setupUi(restore);
-   parent->addWidget(restore);
+   bRestore *brestore = new bRestore(parent);
+   brestore->setupUi(brestore);
+   parent->addWidget(brestore);
 
    /* Just take the first Director */
    LockRes();
    m_dir = (DIRRES *)GetNextRes(R_DIRECTOR, NULL);
    UnlockRes();
 
-   /* Dummy setup of treeWidget */
+   /* ***FIXME*** Dummy setup of treeWidget */
    treeWidget->clear();
    treeWidget->setColumnCount(1);
    treeWidget->setHeaderLabel("Selection");
@@ -75,12 +75,31 @@ Console::Console(QStackedWidget *parent)
    QBrush redBrush(Qt::red);
    item->setForeground(0, redBrush);
    item = new QTreeWidgetItem(topItem);
-   item->setText(0, "Restore");
+   item->setText(0, "brestore");
    item->setText(1, "1");
    treeWidget->expandItem(topItem);
 
    readSettings();
+   /* Check for messages every 5 seconds */
+// m_timer = new QTimer(this);
+// QWidget::connect(m_timer, SIGNAL(timeout()), this, SLOT(poll_messages()));
+// m_timer->start(5000);
+
+}
 
+void Console::poll_messages()
+{
+   m_messages_pending = true;
+}
+
+/* Terminate any open socket */
+void Console::terminate()
+{
+   if (m_sock) {
+      m_sock->close();
+      m_sock = NULL;
+   }
+   m_timer->stop();
 }
 
 /*
@@ -94,18 +113,18 @@ void Console::connect()
    m_textEdit = textEdit;   /* our console screen */
 
    if (!m_dir) {          
-      mainWin->set_status(" No Director found.");
+      mainWin->set_status("No Director found.");
       return;
    }
    if (m_sock) {
-      mainWin->set_status(" Already connected.");
+      mainWin->set_status("Already connected.");
       return;
    }
 
    memset(&jcr, 0, sizeof(jcr));
 
-   mainWin->set_statusf(_(" Connecting to Director %s:%d"), m_dir->address, m_dir->DIRport);
-   set_textf(_("Connecting to Director %s:%d\n\n"), m_dir->address, m_dir->DIRport);
+   mainWin->set_statusf(_("Connecting to Director %s:%d"), m_dir->address, m_dir->DIRport);
+   display_textf(_("Connecting to Director %s:%d\n\n"), m_dir->address, m_dir->DIRport);
 
    /* Give GUI a chance */
    app->processEvents();
@@ -130,19 +149,23 @@ void Console::connect()
    jcr.dir_bsock = m_sock;
 
    if (!authenticate_director(&jcr, m_dir, cons)) {
-      set_text(m_sock->msg);
+      display_text(m_sock->msg);
       return;
    }
 
    /* Give GUI a chance */
    app->processEvents();
 
-   mainWin->set_status(_(" Initializing ..."));
+   mainWin->set_status(_("Initializing ..."));
 
    /* Set up input notifier */
    m_notifier = new QSocketNotifier(m_sock->fd, QSocketNotifier::Read, 0);
    QObject::connect(m_notifier, SIGNAL(activated(int)), this, SLOT(read_dir(int)));
 
+   write(".api");
+   discardToPrompt();
+
+   beginNewCommand();
    job_list = get_list(".jobs");
    client_list = get_list(".clients");
    fileset_list = get_list(".filesets");
@@ -152,7 +175,7 @@ void Console::connect()
    type_list = get_list(".types");
    level_list = get_list(".levels");
 
-   mainWin->set_status(_(" Connected"));
+   mainWin->set_status(_("Connected"));
    return;
 }
 
@@ -173,16 +196,109 @@ QStringList Console::get_list(char *cmd)
       list << msg();
    }
    setEnabled(true);
-   list.sort();
+// list.sort();
    return list;
 }
 
+/*  
+ * Send a job name to the director, and read all the resulting
+ *  defaults. 
+ */
+bool Console::get_job_defaults(struct job_defaults &job_defs)
+{
+   QString scmd;
+   char cmd[1000];
+   int stat;
+   char *def;
+
+   setEnabled(false);
+   beginNewCommand();
+   scmd = QString(".defaults job=\"%1\"").arg(job_defs.job_name);
+   write(scmd);
+   while ((stat = read()) > 0) {
+      def = strchr(msg(), '=');
+      if (!def) {
+         continue;
+      }
+      /* Pointer to default value */
+      *def++ = 0;
+      strip_trailing_junk(def);
+
+      if (strcmp(msg(), "job") == 0) {
+         if (strcmp(def, job_defs.job_name.toUtf8().data()) != 0) {
+            goto bail_out;
+         }
+         continue;
+      }
+      if (strcmp(msg(), "pool") == 0) {
+         job_defs.pool_name = def;
+         continue;
+      }
+      if (strcmp(msg(), "messages") == 0) {
+         job_defs.messages_name = def;
+         continue;
+      }
+      if (strcmp(msg(), "client") == 0) {
+         job_defs.client_name = def;
+         continue;
+      }
+      if (strcmp(msg(), "storage") == 0) {
+         job_defs.store_name = def;
+         continue;
+      }
+      if (strcmp(msg(), "where") == 0) {
+         job_defs.where = def;
+         continue;
+      }
+      if (strcmp(msg(), "level") == 0) {
+         job_defs.level = def;
+         continue;
+      }
+      if (strcmp(msg(), "type") == 0) {
+         job_defs.type = def;
+         continue;
+      }
+      if (strcmp(msg(), "fileset") == 0) {
+         job_defs.fileset_name = def;
+         continue;
+      }
+      if (strcmp(msg(), "catalog") == 0) {
+         job_defs.catalog_name = def;
+         continue;
+      }
+      if (strcmp(msg(), "enabled") == 0) {
+         job_defs.enabled = *def == '1' ? true : false;
+         continue;
+      }
+   }
+   bsnprintf(cmd, sizeof(cmd), "job=%s pool=%s client=%s storage=%s where=%s\n"
+      "level=%s type=%s fileset=%s catalog=%s enabled=%d\n",
+      job_defs.job_name.toUtf8().data(), job_defs.pool_name.toUtf8().data(), 
+      job_defs.client_name.toUtf8().data(), 
+      job_defs.pool_name.toUtf8().data(), job_defs.messages_name.toUtf8().data(), 
+      job_defs.store_name.toUtf8().data(),
+      job_defs.where.toUtf8().data(), job_defs.level.toUtf8().data(), 
+      job_defs.type.toUtf8().data(), job_defs.fileset_name.toUtf8().data(),
+      job_defs.catalog_name.toUtf8().data(), job_defs.enabled);
+
+   setEnabled(true);
+   return true;
+
+bail_out:
+   setEnabled(true);
+   return false;
+}
+
 
+/*
+ * Save user settings associated with this console
+ */
 void Console::writeSettings()
 {
    QFont font = get_font();
 
    QSettings settings("bacula.org", "bat");
+   /* ***FIXME*** make console name unique */
    settings.beginGroup("Console");
    settings.setValue("consoleFont", font.family());
    settings.setValue("consolePointSize", font.pointSize());
@@ -190,6 +306,9 @@ void Console::writeSettings()
    settings.endGroup();
 }
 
+/*
+ * Read and restore user settings associated with this console
+ */
 void Console::readSettings()
 { 
    QFont font = get_font();
@@ -203,6 +322,9 @@ void Console::readSettings()
    m_textEdit->setFont(font);
 }
 
+/*
+ * Set the console textEdit font
+ */
 void Console::set_font()
 {
    bool ok;
@@ -212,6 +334,9 @@ void Console::set_font()
    }
 }
 
+/*
+ * Get the console text edit font
+ */
 const QFont Console::get_font()
 {
    return m_textEdit->font();
@@ -221,9 +346,13 @@ const QFont Console::get_font()
 void Console::status_dir()
 {
    write_dir("status dir\n");
+   displayToPrompt();
 }
 
-void Console::set_textf(const char *fmt, ...)
+/*
+ * Put text into the console window
+ */
+void Console::display_textf(const char *fmt, ...)
 {
    va_list arg_ptr;
    char buf[1000];
@@ -231,17 +360,17 @@ void Console::set_textf(const char *fmt, ...)
    va_start(arg_ptr, fmt);
    len = bvsnprintf(buf, sizeof(buf), fmt, arg_ptr);
    va_end(arg_ptr);
-   set_text(buf);
+   display_text(buf);
 }
 
-void Console::set_text(const QString buf)
+void Console::display_text(const QString buf)
 {
    m_cursor->movePosition(QTextCursor::End);
    m_cursor->insertText(buf);
 }
 
 
-void Console::set_text(const char *buf)
+void Console::display_text(const char *buf)
 {
    m_cursor->movePosition(QTextCursor::End);
    m_cursor->insertText(buf);
@@ -255,6 +384,9 @@ void Console::update_cursor()
    m_textEdit->ensureCursorVisible();
 }
 
+/* 
+ * This should be moved into a bSocket class 
+ */
 char *Console::msg()
 {
    if (m_sock) {
@@ -267,12 +399,9 @@ char *Console::msg()
 void Console::write_dir(const char *msg)
 {
    if (m_sock) {
-      m_at_prompt = false;
-      mainWin->set_status(_(" Processing command ..."));
+      mainWin->set_status(_("Processing command ..."));
       QApplication::setOverrideCursor(Qt::WaitCursor);
-      m_sock->msglen = strlen(msg);
-      pm_strcpy(&m_sock->msg, msg);
-      bnet_send(m_sock);
+      write(msg);
    } else {
       mainWin->set_status(" Director not connected. Click on connect button.");
       mainWin->actionConnect->setIcon(QIcon(QString::fromUtf8("images/disconnected.png")));
@@ -281,32 +410,142 @@ void Console::write_dir(const char *msg)
    }
 }
 
+int Console::write(const QString msg)
+{
+   return write(msg.toUtf8().data());
+}
+
 int Console::write(const char *msg)
 {
    m_sock->msglen = strlen(msg);
    pm_strcpy(&m_sock->msg, msg);
-   return bnet_send(m_sock);
+   m_at_prompt = false;
+   if (commDebug) Pmsg1(000, "send: %s\n", msg);
+   return m_sock->send();
+}
+
+/*
+ * Get to main command prompt 
+ */
+void Console::beginNewCommand()
+{
+   write(".\n");
+   while (read() > 0) {
+   }
+   write(".\n");
+   while (read() > 0) {
+   }
+   write(".\n");
+   while (read() > 0) {
+   }
+   display_text("\n");
+}
+
+void Console::displayToPrompt()
+{ 
+   int stat;
+   if (commDebug) Pmsg0(000, "DisplaytoPrompt\n");
+   m_notifier->setEnabled(false);
+   while ((stat = read()) > 0) {
+      display_text(msg());
+   }
+   if (commDebug) Pmsg1(000, "endDisplaytoPrompt=%d\n", stat);
+   m_notifier->setEnabled(true);
+}
+
+void Console::discardToPrompt()
+{ 
+   int stat;
+   if (commDebug) Pmsg0(000, "discardToPrompt\n");
+   m_notifier->setEnabled(false);
+   while ((stat = read()) > 0) {
+   }
+   if (commDebug) Pmsg1(000, "endDisplayToPrompt=%d\n", stat);
+   m_notifier->setEnabled(true);
 }
 
+
 /* 
- * Blocking read from director */
+ * Blocking read from director
+ */
 int Console::read()
 {
-   int stat;
-   if (m_sock) {
+   int stat = BNET_HARDEOF;
+   while (m_sock) {
       for (;;) {
          stat = bnet_wait_data_intr(m_sock, 1);
          if (stat > 0) {
             break;
          } 
          app->processEvents();
-         if (stat < 0) {
-            return BNET_ERROR;
+//       if (m_api_set && m_messages_pending) {
+//          write_dir(".messages");
+//          m_messages_pending = false;
+//       }
+      }
+      stat = m_sock->recv();
+      if (stat >= 0) {
+         if (m_at_prompt) {
+            display_text("\n");
+            m_at_prompt = false;
          }
+         if (commDebug) Pmsg1(000, "got: %s", m_sock->msg);
+
       }
-      return bnet_recv(m_sock);
+      switch (m_sock->msglen) {
+      case BNET_SERVER_READY:
+//       if (m_api_set && m_messages_pending) {
+//          write_dir(".messages");
+//          m_messages_pending = false;
+//       }
+         m_at_prompt = true;
+         continue;
+      case BNET_MESSAGES_PENDING:
+         m_messages_pending = true;
+         continue;
+      case BNET_CMD_BEGIN:
+         m_at_prompt = false;
+         continue;
+      case BNET_PROMPT:
+      case BNET_CMD_OK:
+         if (commDebug) Pmsg0(000, "CMD OK/PROMPT\n");
+         m_at_prompt = true;
+         mainWin->set_status(_("At prompt waiting for input ..."));
+         update_cursor();
+         QApplication::restoreOverrideCursor();
+         break;
+      case BNET_CMD_FAILED:
+         if (commDebug) Pmsg0(000, "CMD FAIL\n");
+         m_at_prompt = true;
+         mainWin->set_status(_("Command failed. At prompt waiting for input ..."));
+         update_cursor();
+         QApplication::restoreOverrideCursor();
+         break;
+      case BNET_EOD:
+         if (commDebug) Pmsg0(000, "EOD\n");
+         mainWin->set_status_ready();
+         update_cursor();
+         QApplication::restoreOverrideCursor();
+         if (!m_api_set) {
+            break;
+         }
+         continue;
+      }
+      if (is_bnet_stop(m_sock)) {         /* error or term request */
+         m_sock->close();
+         m_sock = NULL;
+         mainWin->actionConnect->setIcon(QIcon(QString::fromUtf8("images/disconnected.png")));
+         QBrush redBrush(Qt::red);
+         m_consoleItem->setForeground(0, redBrush);
+         m_notifier->setEnabled(false);
+         delete m_notifier;
+         m_notifier = NULL;
+         mainWin->set_status(_("Director disconnected."));
+         QApplication::restoreOverrideCursor();
+      }
+      break;
    } 
-   return BNET_HARDEOF;
+   return stat;
 }
 
 /* Called by signal when the Director has output for us */
@@ -315,40 +554,8 @@ void Console::read_dir(int fd)
    int stat;
    (void)fd;
 
-   if (!m_sock) {
-      return;
+   if (commDebug) Pmsg0(000, "read_dir\n");
+   while ((stat = read()) >= 0) {
+      display_text(msg());
    }
-   stat = bnet_recv(m_sock);
-   if (stat >= 0) {
-      if (m_at_prompt) {
-         set_text("\n");
-         m_at_prompt = false;
-      }
-      set_text(m_sock->msg);
-      return;
-   }
-   if (is_bnet_stop(m_sock)) {         /* error or term request */
-      bnet_close(m_sock);
-      m_sock = NULL;
-      mainWin->actionConnect->setIcon(QIcon(QString::fromUtf8("images/disconnected.png")));
-      QBrush redBrush(Qt::red);
-      m_consoleItem->setForeground(0, redBrush);
-      m_notifier->setEnabled(false);
-      delete m_notifier;
-      m_notifier = NULL;
-      mainWin->set_status(_(" Director disconnected."));
-      QApplication::restoreOverrideCursor();
-      return;
-   }
-   /* Must be a signal -- either do something or ignore it */
-   if (m_sock->msglen == BNET_PROMPT) {
-      m_at_prompt = true;
-      mainWin->set_status(_(" At prompt waiting for input ..."));
-      update_cursor();
-   }
-   if (m_sock->msglen == BNET_EOD) {
-      mainWin->set_status_ready();
-      update_cursor();
-   }
-   return;
 }