X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fdird%2Fgetmsg.c;h=18b54e961d8159153b462e9fa401a041ac9a7538;hb=10cfd798ced2d27f61ead2de6fe9b1bcc8e3468d;hp=44c8992a0459e4b1539afdd5bcd3b1fc6e308947;hpb=750c3d37b61a213a1806b4d442484f0988a9409a;p=bacula%2Fbacula diff --git a/bacula/src/dird/getmsg.c b/bacula/src/dird/getmsg.c index 44c8992a04..18b54e961d 100644 --- a/bacula/src/dird/getmsg.c +++ b/bacula/src/dird/getmsg.c @@ -1,3 +1,21 @@ +/* + Bacula(R) - The Network Backup Solution + + Copyright (C) 2000-2018 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. +*/ /* * * Bacula Director -- routines to receive network data and @@ -18,35 +36,7 @@ * Requests are any message that does not begin with a digit. * In affect, they are commands. * - * Version $Id$ */ -/* - Bacula® - The Network Backup Solution - - Copyright (C) 2000-2006 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 plus additions - that are listed 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 John Walker. - The licensor of Bacula is the Free Software Foundation Europe - (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, - Switzerland, email:ftf@fsfeurope.org. -*/ #include "bacula.h" #include "dird.h" @@ -54,9 +44,9 @@ /* Forward referenced functions */ static char *find_msg_start(char *msg); -static char Job_status[] = "Status Job=%127s JobStatus=%d\n"; +static char Job_status[] = "Status JobId=%ld JobStatus=%d\n"; #ifdef needed -static char Device_update[] = "DevUpd Job=%127s " +static char Device_update[] = "DevUpd JobId=%127s " "device=%127s " "append=%d read=%d num_writers=%d " "open=%d labeled=%d offline=%d " @@ -70,6 +60,54 @@ static char Device_update[] = "DevUpd Job=%127s " static char OK_msg[] = "1000 OK\n"; + +static 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; + if (jcr->SDJobStatus == JS_Incomplete) { + jcr->setJobStatus(JS_Incomplete); + } + +} + +/* + * See if we are pointing to a message id + * Look for: [XYnnnn] + */ +static bool is_msgid(char *msg) +{ + if (!msg) return false; + char *end = strchr(msg, ']'); + if (!end) return false; + if ((end - msg) != 7) return false; + if (!B_ISUPPER(msg[1]) || !B_ISUPPER(msg[2])) return false; + for (int i=3; i<7; i++) { + if (!B_ISDIGIT(msg[i])) return false; + } + return true; +} + /* * Get a message * Call appropriate processing routine @@ -82,34 +120,37 @@ static char OK_msg[] = "1000 OK\n"; * to the appropriate handler. If the message is * in any other format, it will be returned. * - * E.g. any message beginning with a digit will be passed + * E.g. any message beginning with a digit will be passed * 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, ...) - * could be checked. This is followed by Job=Jobname + * could be checked. + * This is followed by JobId=nnn * info. The identifier is used to dispatch the message to the right * place (Job message, catalog request, ...). The Job is used to lookup * the JCR so that the action is performed on the correct jcr, and * the rest of the message is up to the user. Note, DevUpd uses - * *System* for the Job name, and hence no JCR is obtained. This + * *System* for the Job name, and hence no JCR is obtained. This * is a *rare* case where a jcr is not really needed. * */ int bget_dirmsg(BSOCK *bs) { - int32_t n; + int32_t n = BNET_TERMINATE; char Job[MAX_NAME_LENGTH]; + JobId_t JobId = 0; char MsgType[20]; - int type, level; - JCR *jcr; + int type; + utime_t mtime; /* message time */ + JCR *jcr = bs->jcr(); char *msg; - for (;;) { + for ( ; !bs->is_stop() && !bs->is_timed_out(); ) { n = bs->recv(); - Dmsg2(900, "bget_dirmsg %d: %s", n, bs->msg); + Dmsg4(200, "bget_dirmsg n=%d msglen=%ld is_stop=%d: %s\n", n, bs->msglen, bs->is_stop(), bs->msg); - if (is_bnet_stop(bs)) { + if (bs->is_stop() || bs->is_timed_out()) { return n; /* error or terminate */ } if (n == BNET_SIGNAL) { /* handle signal */ @@ -121,7 +162,7 @@ int bget_dirmsg(BSOCK *bs) bs->fsend(OK_msg);/* send response */ return n; /* end of data */ case BNET_TERMINATE: - bs->m_terminated = 1; + bs->set_terminated(); return n; case BNET_POLL: bs->fsend(OK_msg); /* send response */ @@ -142,7 +183,7 @@ int bget_dirmsg(BSOCK *bs) bs->fsend("btime %s\n", edit_uint64(get_current_btime(),ed1)); break; default: - Emsg1(M_WARNING, 0, _("bget_dirmsg: unknown bnet signal %d\n"), bs->msglen); + Jmsg1(jcr, M_WARNING, 0, _("bget_dirmsg: unknown bnet signal %d\n"), bs->msglen); return n; } continue; @@ -159,34 +200,34 @@ int bget_dirmsg(BSOCK *bs) * 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); + if ((sscanf(bs->msg, "%020s JobId=%ld ", MsgType, &JobId) != 2) && + (sscanf(bs->msg, "%020s Job=%127s ", MsgType, Job) != 2) && + (sscanf(bs->msg, "%020s Job=x", MsgType) != 1)) { + if (is_msgid(strchr(bs->msg, '['))) { + return n; + } + 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" */ + /* Skip past first two fields: "Jmsg JobId=nnn" */ if (!(msg=find_msg_start(bs->msg))) { - Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg); - free_jcr(jcr); + 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 + * Jmsg JobId=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); + if ((sscanf(bs->msg, "Jmsg JobId=%ld type=%d level=%lld", + &JobId, &type, &mtime) != 3) && + (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); @@ -198,43 +239,71 @@ int bget_dirmsg(BSOCK *bs) msg++; /* skip leading space */ } Dmsg1(900, "Dispatch msg: %s", msg); - dispatch_message(jcr, type, level, msg); - free_jcr(jcr); + dispatch_message(jcr, type, mtime, msg); continue; } /* * Here we expact a CatReq message - * CatReq Job=nn Catalog-Request-Message + * CatReq JobId=nn Catalog-Request-Message */ if (bs->msg[0] == 'C') { /* Catalog request */ - Dmsg2(900, "Catalog req jcr 0x%x: %s", jcr, bs->msg); + Dmsg2(900, "Catalog req jcr=%p: %s", jcr, bs->msg); catalog_request(jcr, bs); - Dmsg1(900, "Calling freejcr 0x%x\n", jcr); - free_jcr(jcr); continue; } - if (bs->msg[0] == 'U') { /* Catalog update */ - Dmsg2(900, "Catalog upd jcr 0x%x: %s", jcr, bs->msg); + if (bs->msg[0] == 'U') { /* SD sending attributes */ + Dmsg2(900, "Catalog upd jcr=%p: %s", jcr, bs->msg); catalog_update(jcr, bs); - Dmsg1(900, "Calling freejcr 0x%x\n", jcr); - free_jcr(jcr); + continue; + } + if (bs->msg[0] == 'B') { /* SD sending file spool attributes */ + Dmsg2(100, "Blast attributes jcr=%p: %s", jcr, bs->msg); + char filename[256]; + if (sscanf(bs->msg, "BlastAttr JobId=%ld File=%255s", + &JobId, filename) != 2) { + Jmsg1(jcr, M_ERROR, 0, _("Malformed message: %s\n"), bs->msg); + continue; + } + unbash_spaces(filename); + if (despool_attributes_from_file(jcr, filename)) { + bs->fsend("1000 OK BlastAttr\n"); + } else { + bs->fsend("1990 ERROR BlastAttr\n"); + } continue; } if (bs->msg[0] == 'M') { /* Mount request */ Dmsg1(900, "Mount req: %s", bs->msg); mount_request(jcr, bs, msg); - free_jcr(jcr); + continue; + } + /* Get Progress: files, bytes, bytes/sec */ + if (bs->msg[0] == 'P') { /* Progress report */ + uint32_t files, bps; + uint64_t bytes; + if ((sscanf(bs->msg, "Progress JobId=%ld files=%ld bytes=%lld bps=%ld\n", + &JobId, &files, &bytes, &bps) == 4) || + (sscanf(bs->msg, "Progress JobId=x files=%ld bytes=%lld bps=%ld\n", + &files, &bytes, &bps) == 3) || + (sscanf(bs->msg, "Progress Job=x files=%ld bytes=%lld bps=%ld\n", + &files, &bytes, &bps) == 3)) { + Dmsg2(900, "JobId=%d %s", jcr->JobId, bs->msg); + /* Save progress data */ + jcr->JobFiles = files; + jcr->JobBytes = bytes; + jcr->LastRate = bps; + } else { + Jmsg1(jcr, M_ERROR, 0, _("Malformed message: %s\n"), 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 */ + if (sscanf(bs->msg, Job_status, &JobId, &JobStatus) == 2) { + set_jcr_sd_job_status(jcr, JobStatus); /* current status */ } else { - Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg); + Jmsg1(jcr, M_ERROR, 0, _("Malformed message: %s\n"), bs->msg); } - free_jcr(jcr); continue; } #ifdef needed @@ -253,8 +322,8 @@ int bget_dirmsg(BSOCK *bs) &dev_append, &dev_read, &dev_num_writers, &dev_open, &dev_labeled, &dev_offline, &dev_reserved, - &dev_max_writers, &dev_autoselect, - &dev_autochanger, + &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, @@ -298,6 +367,7 @@ int bget_dirmsg(BSOCK *bs) #endif return n; } + return n; } static char *find_msg_start(char *msg) @@ -322,7 +392,7 @@ bool response(JCR *jcr, BSOCK *bs, char *resp, const char *cmd, e_prtmsg prtmsg) { int n; - if (is_bnet_error(bs)) { + if (bs->is_error()) { return false; } if ((n = bget_dirmsg(bs)) >= 0) { @@ -336,6 +406,6 @@ bool response(JCR *jcr, BSOCK *bs, char *resp, const char *cmd, e_prtmsg prtmsg) return false; } Jmsg(jcr, M_FATAL, 0, _("Socket error on %s command: ERR=%s\n"), - cmd, bnet_strerror(bs)); + cmd, bs->bstrerror()); return false; }