]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/dird/getmsg.c
Remove all time_t from arguments in favor of utime_t, which is
[bacula/bacula] / bacula / src / dird / getmsg.c
index aafbd42d0cda43d3f5d9ea131b35a769d1e7c5f2..c0237489b46547dd164df760b67b97770829c7ed 100644 (file)
@@ -1,3 +1,30 @@
+/*
+   Bacula® - The Network Backup Solution
+
+   Copyright (C) 2000-2008 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 Director -- routines to receive network data and
  *
  *  Basic tasks done here:
  *    Handle  network signals (signals).
- *      Signals always have return status 0 from bnet_recv() and
- *      a zero or negative message length.
+ *       Signals always have return status 0 from bnet_recv() and
+ *       a zero or negative message length.
  *    Pass appropriate messages back to the caller (responses).
- *      Responses always have a digit as the first character.
+ *       Responses always have a digit as the first character.
  *    Handle requests for message and catalog services (requests).
- *      Requests are any message that does not begin with a digit.
- *      In affect, they are commands.
+ *       Requests are any message that does not begin with a digit.
+ *       In affect, they are commands.
  *
  *   Version $Id$
  */
-/*
-   Copyright (C) 2000-2005 Kern Sibbald
-
-   This program is free software; you can redistribute it and/or
-   modify it under the terms of the GNU General Public License as
-   published by the Free Software Foundation; either version 2 of
-   the License, or (at your option) any later version.
-
-   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., 59 Temple Place - Suite 330, Boston,
-   MA 02111-1307, USA.
-
- */
 
 #include "bacula.h"
 #include "dird.h"
@@ -54,12 +62,41 @@ static char Device_update[]   = "DevUpd Job=%127s "
    "open=%d labeled=%d offline=%d "
    "reserved=%d max_writers=%d "
    "autoselect=%d autochanger=%d "
-   "changer_name=%127s media_type=%127s volume_name=%127s\n";
+   "changer_name=%127s media_type=%127s volume_name=%127s "
+   "DevReadTime=%d DevWriteTime=%d DevReadBytes=%d "
+   "DevWriteBytes=%d\n";
 #endif
 
 
 static char OK_msg[] = "1000 OK\n";
 
+
+void set_jcr_sd_job_status(JCR *jcr, int SDJobStatus)
+{
+   bool set_waittime=false;
+   Dmsg2(800, "set_jcr_sd_job_status(%s, %c)\n", jcr->Job, SDJobStatus);
+   /* if wait state is new, we keep current time for watchdog MaxWaitTime */
+   switch (SDJobStatus) {
+      case JS_WaitMedia:
+      case JS_WaitMount:
+      case JS_WaitMaxJobs:
+         set_waittime = true;
+      default:
+         break;
+   }
+
+   if (job_waiting(jcr)) {
+      set_waittime = false;
+   }
+
+   if (set_waittime) {
+      /* set it before JobStatus */
+      Dmsg0(800, "Setting wait_time\n");
+      jcr->wait_time = time(NULL);
+   }
+   jcr->SDJobStatus = SDJobStatus;
+}
+
 /*
  * Get a message
  *  Call appropriate processing routine
@@ -73,7 +110,7 @@ static char OK_msg[] = "1000 OK\n";
  *  in any other format, it will be returned.
  *
  *  E.g. any message beginning with a digit will be passed   
- *      through to the caller.
+ *       through to the caller.
  *  All other messages are expected begin with some identifier
  *    -- for the moment only the first character is checked, but
  *    at a later time, the whole identifier (e.g. Jmsg, CatReq, ...)
@@ -91,106 +128,99 @@ int bget_dirmsg(BSOCK *bs)
    int32_t n;
    char Job[MAX_NAME_LENGTH];
    char MsgType[20];
-   int type, level;
-   JCR *jcr;
+   int type;
+   utime_t mtime;                     /* message time */
+   JCR *jcr = bs->jcr();
    char *msg;
 
    for (;;) {
-      n = bnet_recv(bs);
-      Dmsg2(900, "bget_dirmsg %d: %s", n, bs->msg);
+      n = bs->recv();
+      Dmsg2(300, "bget_dirmsg %d: %s\n", n, bs->msg);
 
       if (is_bnet_stop(bs)) {
-        return n;                    /* error or terminate */
+         return n;                    /* error or terminate */
       }
-      if (n == BNET_SIGNAL) {         /* handle signal */
-        /* BNET_SIGNAL (-1) return from bnet_recv() => network signal */
-        switch (bs->msglen) {
-        case BNET_EOD:            /* end of data */
-           return n;
-        case BNET_EOD_POLL:
-           bnet_fsend(bs, OK_msg);/* send response */
-           return n;              /* end of data */
-        case BNET_TERMINATE:
-           bs->terminated = 1;
-           return n;
-        case BNET_POLL:
-           bnet_fsend(bs, OK_msg); /* send response */
-           break;
-        case BNET_HEARTBEAT:
-//         encode_time(time(NULL), Job);
+      if (n == BNET_SIGNAL) {          /* handle signal */
+         /* BNET_SIGNAL (-1) return from bnet_recv() => network signal */
+         switch (bs->msglen) {
+         case BNET_EOD:            /* end of data */
+            return n;
+         case BNET_EOD_POLL:
+            bs->fsend(OK_msg);/* send response */
+            return n;              /* end of data */
+         case BNET_TERMINATE:
+            bs->set_terminated();
+            return n;
+         case BNET_POLL:
+            bs->fsend(OK_msg); /* send response */
+            break;
+         case BNET_HEARTBEAT:
+//          encode_time(time(NULL), Job);
 //          Dmsg1(100, "%s got heartbeat.\n", Job);
-           break;
-        case BNET_HB_RESPONSE:
-           break;
-        case BNET_STATUS:
-           /* *****FIXME***** Implement more completely */
-            bnet_fsend(bs, "Status OK\n");
-           bnet_sig(bs, BNET_EOD);
-           break;
-        case BNET_BTIME:             /* send Bacula time */
-           char ed1[50];
-            bnet_fsend(bs, "btime %s\n", edit_uint64(get_current_btime(),ed1));
-           break;
-        default:
-            Emsg1(M_WARNING, 0, _("bget_dirmsg: unknown bnet signal %d\n"), bs->msglen);
-           return n;
-        }
-        continue;
+            break;
+         case BNET_HB_RESPONSE:
+            break;
+         case BNET_STATUS:
+            /* *****FIXME***** Implement more completely */
+            bs->fsend("Status OK\n");
+            bs->signal(BNET_EOD);
+            break;
+         case BNET_BTIME:             /* send Bacula time */
+            char ed1[50];
+            bs->fsend("btime %s\n", edit_uint64(get_current_btime(),ed1));
+            break;
+         default:
+            Jmsg1(jcr, M_WARNING, 0, _("bget_dirmsg: unknown bnet signal %d\n"), bs->msglen);
+            return n;
+         }
+         continue;
       }
 
       /* Handle normal data */
 
-      if (n > 0 && B_ISDIGIT(bs->msg[0])) {     /* response? */
-        return n;                    /* yes, return it */
+      if (n > 0 && B_ISDIGIT(bs->msg[0])) {      /* response? */
+         return n;                    /* yes, return it */
       }
 
       /*
-       * If we get here, it must be a request. Either
+       * If we get here, it must be a request.  Either
        *  a message to dispatch, or a catalog request.
        *  Try to fulfill it.
        */
       if (sscanf(bs->msg, "%020s Job=%127s ", MsgType, Job) != 2) {
-         Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
-        continue;
-      }
-      if (strcmp(Job, "*System*") == 0) {
-        jcr = NULL;                  /* No jcr */
-      } else if (!(jcr=get_jcr_by_full_name(Job))) {
-         Emsg1(M_ERROR, 0, _("Job not found: %s\n"), bs->msg);
-        continue;
+         Jmsg1(jcr, M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
+         continue;
       }
-      Dmsg1(900, "Getmsg got jcr 0x%x\n", jcr);
 
       /* Skip past "Jmsg Job=nnn" */
       if (!(msg=find_msg_start(bs->msg))) {
-         Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
-        free_jcr(jcr);
-        continue;
+         Jmsg1(jcr, M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
+         continue;
       }
 
       /*
        * Here we are expecting a message of the following format:
        *   Jmsg Job=nnn type=nnn level=nnn Message-string
+       * Note, level should really be mtime, but that changes
+       *   the protocol.
        */
       if (bs->msg[0] == 'J') {           /* Job message */
-         if (sscanf(bs->msg, "Jmsg Job=%127s type=%d level=%d",
-                   Job, &type, &level) != 3) {
-            Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
-           free_jcr(jcr);
-           continue;
-        }
+         if (sscanf(bs->msg, "Jmsg Job=%127s type=%d level=%lld",
+                    Job, &type, &mtime) != 3) {
+            Jmsg1(jcr, M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
+            continue;
+         }
          Dmsg1(900, "Got msg: %s\n", bs->msg);
-        skip_spaces(&msg);
-        skip_nonspaces(&msg);        /* skip type=nnn */
-        skip_spaces(&msg);
-        skip_nonspaces(&msg);        /* skip level=nnn */
+         skip_spaces(&msg);
+         skip_nonspaces(&msg);        /* skip type=nnn */
+         skip_spaces(&msg);
+         skip_nonspaces(&msg);        /* skip level=nnn */
          if (*msg == ' ') {
-           msg++;                    /* skip leading space */
-        }
+            msg++;                    /* skip leading space */
+         }
          Dmsg1(900, "Dispatch msg: %s", msg);
-        dispatch_message(jcr, type, level, msg);
-        free_jcr(jcr);
-        continue;
+         dispatch_message(jcr, type, mtime, msg);
+         continue;
       }
       /*
        * Here we expact a CatReq message
@@ -198,85 +228,86 @@ int bget_dirmsg(BSOCK *bs)
        */
       if (bs->msg[0] == 'C') {        /* Catalog request */
          Dmsg2(900, "Catalog req jcr 0x%x: %s", jcr, bs->msg);
-        catalog_request(jcr, bs, msg);
-         Dmsg1(900, "Calling freejcr 0x%x\n", jcr);
-        free_jcr(jcr);
-        continue;
+         catalog_request(jcr, bs);
+         continue;
       }
-      if (bs->msg[0] == 'U') {        /* Catalog update */
+      if (bs->msg[0] == 'U') {        /* SD sending attributes */
          Dmsg2(900, "Catalog upd jcr 0x%x: %s", jcr, bs->msg);
-        catalog_update(jcr, bs, msg);
-         Dmsg1(900, "Calling freejcr 0x%x\n", jcr);
-        free_jcr(jcr);
-        continue;
+         catalog_update(jcr, bs);
+         continue;
       }
       if (bs->msg[0] == 'M') {        /* Mount request */
          Dmsg1(900, "Mount req: %s", bs->msg);
-        mount_request(jcr, bs, msg);
-        free_jcr(jcr);
-        continue;
+         mount_request(jcr, bs, msg);
+         continue;
       }
       if (bs->msg[0] == 'S') {       /* Status change */
-        int JobStatus;
-        char Job[MAX_NAME_LENGTH];
-        if (sscanf(bs->msg, Job_status, &Job, &JobStatus) == 2) {
-           jcr->SDJobStatus = JobStatus; /* current status */
-        } else {
-            Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
-        }
-        free_jcr(jcr);
-        continue;
+         int JobStatus;
+         char Job[MAX_NAME_LENGTH];
+         if (sscanf(bs->msg, Job_status, &Job, &JobStatus) == 2) {
+            set_jcr_sd_job_status(jcr, JobStatus); /* current status */
+         } else {
+            Jmsg1(jcr, M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
+         }
+         continue;
       }
-#ifdef needec
+#ifdef needed
       /* No JCR for Device Updates! */
       if (bs->msg[0] = 'D') {         /* Device update */
-        DEVICE *dev;
-        POOL_MEM dev_name, changer_name, media_type, volume_name;
-        int dev_open, dev_append, dev_read, dev_labeled;
-        int dev_offline, dev_autochanger, dev_autoselect;
-        int dev_num_writers, dev_max_writers, dev_reserved;
-        uint64_t dev_PoolId;
+         DEVICE *dev;
+         POOL_MEM dev_name, changer_name, media_type, volume_name;
+         int dev_open, dev_append, dev_read, dev_labeled;
+         int dev_offline, dev_autochanger, dev_autoselect;
+         int dev_num_writers, dev_max_writers, dev_reserved;
+         uint64_t dev_read_time, dev_write_time, dev_write_bytes, dev_read_bytes;
+         uint64_t dev_PoolId;
          Dmsg1(100, "<stored: %s", bs->msg);
-        if (sscanf(bs->msg, Device_update,
-            &Job, dev_name.c_str(),
-            &dev_append, &dev_read,
-            &dev_num_writers, &dev_open,
-            &dev_labeled, &dev_offline, &dev_reserved,
-            &dev_max_writers, &dev_autoselect, 
-            &dev_autochanger, 
-            changer_name.c_str(), media_type.c_str(),
-            volume_name.c_str()) != 15) {
+         if (sscanf(bs->msg, Device_update,
+             &Job, dev_name.c_str(),
+             &dev_append, &dev_read,
+             &dev_num_writers, &dev_open,
+             &dev_labeled, &dev_offline, &dev_reserved,
+             &dev_max_writers, &dev_autoselect, 
+             &dev_autochanger, 
+             changer_name.c_str(), media_type.c_str(),
+             volume_name.c_str(),
+             &dev_read_time, &dev_write_time, &dev_read_bytes,
+             &dev_write_bytes) != 19) {
             Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg);
-        } else {
-           unbash_spaces(dev_name);
-           dev = (DEVICE *)GetResWithName(R_DEVICE, dev_name.c_str());
-           if (!dev) {
-              continue;
-           }
-           unbash_spaces(changer_name);
-           unbash_spaces(media_type);
-           unbash_spaces(volume_name);
-           bstrncpy(dev->ChangerName, changer_name.c_str(), sizeof(dev->ChangerName));
-           bstrncpy(dev->MediaType, media_type.c_str(), sizeof(dev->MediaType));
-           bstrncpy(dev->VolumeName, volume_name.c_str(), sizeof(dev->VolumeName));
-           /* Note, these are copied because they are boolean rather than
-            *  integer.
-            */
-           dev->open = dev_open;
-           dev->append = dev_append;
-           dev->read = dev_read;
-           dev->labeled = dev_labeled;
-           dev->offline = dev_offline;
-           dev->autoselect = dev_autoselect;
-           dev->autochanger = dev_autochanger > 0;
-           dev->num_drives = dev_autochanger;    /* does double duty */
-           dev->PoolId = dev_PoolId;
-           dev->num_writers = dev_num_writers;
-           dev->max_writers = dev_max_writers;
-           dev->reserved = dev_reserved;
-           dev->found = true;
-        }
-        continue;
+         } else {
+            unbash_spaces(dev_name);
+            dev = (DEVICE *)GetResWithName(R_DEVICE, dev_name.c_str());
+            if (!dev) {
+               continue;
+            }
+            unbash_spaces(changer_name);
+            unbash_spaces(media_type);
+            unbash_spaces(volume_name);
+            bstrncpy(dev->ChangerName, changer_name.c_str(), sizeof(dev->ChangerName));
+            bstrncpy(dev->MediaType, media_type.c_str(), sizeof(dev->MediaType));
+            bstrncpy(dev->VolumeName, volume_name.c_str(), sizeof(dev->VolumeName));
+            /* Note, these are copied because they are boolean rather than
+             *  integer.
+             */
+            dev->open = dev_open;
+            dev->append = dev_append;
+            dev->read = dev_read;
+            dev->labeled = dev_labeled;
+            dev->offline = dev_offline;
+            dev->autoselect = dev_autoselect;
+            dev->autochanger = dev_autochanger > 0;
+            dev->num_drives = dev_autochanger;    /* does double duty */
+            dev->PoolId = dev_PoolId;
+            dev->num_writers = dev_num_writers;
+            dev->max_writers = dev_max_writers;
+            dev->reserved = dev_reserved;
+            dev->found = true;
+            dev->DevReadTime = dev_read_time; /* TODO : have to update database */
+            dev->DevWriteTime = dev_write_time;
+            dev->DevReadBytes = dev_read_bytes;
+            dev->DevWriteBytes = dev_write_bytes;
+         }
+         continue;
       }
 #endif
       return n;
@@ -287,10 +318,10 @@ static char *find_msg_start(char *msg)
 {
    char *p = msg;
 
-   skip_nonspaces(&p);               /* skip message type */
+   skip_nonspaces(&p);                /* skip message type */
    skip_spaces(&p);
-   skip_nonspaces(&p);               /* skip Job */
-   skip_spaces(&p);                  /* after spaces come the message */
+   skip_nonspaces(&p);                /* skip Job */
+   skip_spaces(&p);                   /* after spaces come the message */
    return p;
 }
 
@@ -299,7 +330,7 @@ static char *find_msg_start(char *msg)
  * sent. Check that the response agrees with what we expect.
  *
  *  Returns: false on failure
- *          true  on success
+ *           true  on success
  */
 bool response(JCR *jcr, BSOCK *bs, char *resp, const char *cmd, e_prtmsg prtmsg)
 {
@@ -309,18 +340,16 @@ bool response(JCR *jcr, BSOCK *bs, char *resp, const char *cmd, e_prtmsg prtmsg)
       return false;
    }
    if ((n = bget_dirmsg(bs)) >= 0) {
-      Dmsg0(900, bs->msg);
       if (strcmp(bs->msg, resp) == 0) {
-        return true;
+         return true;
       }
-      Dmsg1(900, "Bad response: ERR=%s", bs->msg);
       if (prtmsg == DISPLAY_ERROR) {
-         Jmsg(jcr, M_FATAL, 0, _("Bad response to %s command: wanted %s got: %s\n"),
-           cmd, resp, bs->msg);
+         Jmsg(jcr, M_FATAL, 0, _("Bad response to %s command: wanted %s, got %s\n"),
+            cmd, resp, bs->msg);
       }
       return false;
    }
    Jmsg(jcr, M_FATAL, 0, _("Socket error on %s command: ERR=%s\n"),
-        cmd, bnet_strerror(bs));
+         cmd, bnet_strerror(bs));
    return false;
 }