X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fstored%2Faskdir.c;h=898dfa093f40c97e5618c83d0a419080b34c6a07;hb=79822b6b171cc2af23c6f3cd1608c59e15897a84;hp=96ba8d1de0e628fa20eaf1834082ff8c7478083b;hpb=29ae1ea61c62a64cfd7f79528420397ac10551fe;p=bacula%2Fbacula diff --git a/bacula/src/stored/askdir.c b/bacula/src/stored/askdir.c index 96ba8d1de0..898dfa093f 100644 --- a/bacula/src/stored/askdir.c +++ b/bacula/src/stored/askdir.c @@ -1,12 +1,12 @@ /* Bacula® - The Network Backup Solution - Copyright (C) 2000-2008 Free Software Foundation Europe e.V. + Copyright (C) 2000-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,12 +15,12 @@ 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. - Bacula® is a registered trademark of John Walker. + 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. @@ -31,7 +31,6 @@ * * Kern Sibbald, December 2000 * - * Version $Id$ */ #include "bacula.h" /* pull in global headers */ @@ -74,7 +73,7 @@ static char Device_update[] = "DevUpd Job=%s device=%s " "changer_name=%s media_type=%s volume_name=%s\n"; -/* Send update information about a device to Director */ +/** Send update information about a device to Director */ bool dir_update_device(JCR *jcr, DEVICE *dev) { BSOCK *dir = jcr->dir_bsock; @@ -143,7 +142,7 @@ bool dir_update_changer(JCR *jcr, AUTOCHANGER *changer) #endif -/* +/** * Send current JobStatus to Director */ bool dir_send_job_status(JCR *jcr) @@ -151,7 +150,7 @@ bool dir_send_job_status(JCR *jcr) return jcr->dir_bsock->fsend(Job_status, jcr->Job, jcr->JobStatus); } -/* +/** * Common routine for: * dir_get_volume_info() * and @@ -173,6 +172,7 @@ static bool do_get_volume_info(DCR *dcr) int n; int32_t InChanger; + dcr->setVolCatInfo(false); if (dir->recv() <= 0) { Dmsg0(200, "getvolname error bnet_recv\n"); Mmsg(jcr->errmsg, _("Network error on bnet_recv in req_vol_info.\n")); @@ -197,6 +197,7 @@ static bool do_get_volume_info(DCR *dcr) return false; } vol.InChanger = InChanger; /* bool in structure */ + vol.is_valid = true; unbash_spaces(vol.VolCatName); bstrncpy(dcr->VolumeName, vol.VolCatName, sizeof(dcr->VolumeName)); dcr->VolCatInfo = vol; /* structure assignment */ @@ -207,7 +208,7 @@ static bool do_get_volume_info(DCR *dcr) } -/* +/** * Get Volume info for a specific volume from the Director's Database * * Returns: true on success (Director guarantees that Pool and MediaType @@ -223,12 +224,12 @@ bool dir_get_volume_info(DCR *dcr, enum get_vol_info_rw writing) BSOCK *dir = jcr->dir_bsock; P(vol_info_mutex); - bstrncpy(dcr->VolCatInfo.VolCatName, dcr->VolumeName, sizeof(dcr->VolCatInfo.VolCatName)); - bash_spaces(dcr->VolCatInfo.VolCatName); - dir->fsend(Get_Vol_Info, jcr->Job, dcr->VolCatInfo.VolCatName, + dcr->setVolCatName(dcr->VolumeName); + bash_spaces(dcr->getVolCatName()); + dir->fsend(Get_Vol_Info, jcr->Job, dcr->getVolCatName(), writing==GET_VOL_INFO_FOR_WRITE?1:0); Dmsg1(100, ">dird %s", dir->msg); - unbash_spaces(dcr->VolCatInfo.VolCatName); + unbash_spaces(dcr->getVolCatName()); bool ok = do_get_volume_info(dcr); V(vol_info_mutex); return ok; @@ -236,13 +237,13 @@ bool dir_get_volume_info(DCR *dcr, enum get_vol_info_rw writing) -/* +/** * Get info on the next appendable volume in the Director's database * * Returns: true on success dcr->VolumeName is volume * reserve_volume() called on Volume name * false on failure dcr->VolumeName[0] == 0 - * also sets dcr->volume_in_use if at least one + * also sets dcr->found_in_use if at least one * in use volume was found. * * Volume information returned in dcr @@ -253,19 +254,21 @@ bool dir_find_next_appendable_volume(DCR *dcr) JCR *jcr = dcr->jcr; BSOCK *dir = jcr->dir_bsock; bool rtn; + char lastVolume[MAX_NAME_LENGTH]; Dmsg2(200, "dir_find_next_appendable_volume: reserved=%d Vol=%s\n", - dcr->reserved_device, dcr->VolumeName); + dcr->is_reserved(), dcr->VolumeName); /* - * Try the fourty oldest or most available volumes. Note, + * Try the twenty oldest or most available volumes. Note, * the most available could already be mounted on another * drive, so we continue looking for a not in use Volume. */ lock_volumes(); P(vol_info_mutex); - dcr->volume_in_use = false; - for (int vol_index=1; vol_index < 40; vol_index++) { + dcr->clear_found_in_use(); + lastVolume[0] = 0; + for (int vol_index=1; vol_index < 20; vol_index++) { bash_spaces(dcr->media_type); bash_spaces(dcr->pool_name); dir->fsend(Find_media, jcr->Job, vol_index, dcr->pool_name, dcr->media_type); @@ -273,9 +276,15 @@ bool dir_find_next_appendable_volume(DCR *dcr) unbash_spaces(dcr->pool_name); Dmsg1(100, ">dird %s", dir->msg); if (do_get_volume_info(dcr)) { - if (!is_volume_in_use(dcr)) { + /* Give up if we get the same volume name twice */ + if (lastVolume[0] && strcmp(lastVolume, dcr->VolumeName) == 0) { + Dmsg1(100, "Got same vol = %s\n", lastVolume); + break; + } + bstrncpy(lastVolume, dcr->VolumeName, sizeof(lastVolume)); + if (dcr->can_i_write_volume()) { Dmsg1(100, "Call reserve_volume. Vol=%s\n", dcr->VolumeName); - if (reserve_volume(dcr, dcr->VolumeName) == 0) { + if (reserve_volume(dcr, dcr->VolumeName) == NULL) { Dmsg2(100, "Could not reserve volume %s on %s\n", dcr->VolumeName, dcr->dev->print_name()); continue; @@ -286,7 +295,8 @@ bool dir_find_next_appendable_volume(DCR *dcr) goto get_out; } else { Dmsg1(100, "Volume %s is in use.\n", dcr->VolumeName); - dcr->volume_in_use = true; + /* If volume is not usable, it is in use by someone else */ + dcr->set_found_in_use(); continue; } } @@ -304,7 +314,7 @@ get_out: } -/* +/** * After writing a Volume, send the updated statistics * back to the director. The information comes from the * dev record. @@ -321,7 +331,7 @@ bool dir_update_volume_info(DCR *dcr, bool label, bool update_LastWritten) POOL_MEM VolumeName; /* If system job, do not update catalog */ - if (jcr->JobType == JT_SYSTEM) { + if (jcr->getJobType() == JT_SYSTEM) { return true; } @@ -333,7 +343,7 @@ bool dir_update_volume_info(DCR *dcr, bool label, bool update_LastWritten) /* Lock during Volume update */ P(vol_info_mutex); - Dmsg1(100, "Update cat VolFiles=%d\n", dev->file); + Dmsg1(100, "Update cat VolBytes=%lld\n", vol->VolCatBytes); /* Just labeled or relabeled the tape */ if (label) { bstrncpy(vol->VolCatStatus, "Append", sizeof(vol->VolCatStatus)); @@ -375,17 +385,24 @@ bail_out: return ok; } -/* +/** * After writing a Volume, create the JobMedia record. */ -bool dir_create_jobmedia_record(DCR *dcr) +bool dir_create_jobmedia_record(DCR *dcr, bool zero) { JCR *jcr = dcr->jcr; BSOCK *dir = jcr->dir_bsock; char ed1[50]; /* If system job, do not update catalog */ - if (jcr->JobType == JT_SYSTEM) { + if (jcr->getJobType() == JT_SYSTEM) { + return true; + } + + /* Throw out records where FI is zero -- i.e. nothing done */ + if (!zero && dcr->VolFirstIndex == 0 && + (dcr->StartBlock != 0 || dcr->EndBlock != 0)) { + Dmsg0(100, "JobMedia FI=0 StartBlock!=0 record suppressed\n"); return true; } @@ -394,13 +411,19 @@ bool dir_create_jobmedia_record(DCR *dcr) } dcr->WroteVol = false; - dir->fsend(Create_job_media, jcr->Job, - dcr->VolFirstIndex, dcr->VolLastIndex, - dcr->StartFile, dcr->EndFile, - dcr->StartBlock, dcr->EndBlock, - dcr->Copy, dcr->Stripe, - edit_uint64(dcr->VolMediaId, ed1)); - Dmsg1(100, ">dird %s", dir->msg); + if (zero) { + /* Send dummy place holder to avoid purging */ + dir->fsend(Create_job_media, jcr->Job, + 0 , 0, 0, 0, 0, 0, 0, 0, edit_uint64(dcr->VolMediaId, ed1)); + } else { + dir->fsend(Create_job_media, jcr->Job, + dcr->VolFirstIndex, dcr->VolLastIndex, + dcr->StartFile, dcr->EndFile, + dcr->StartBlock, dcr->EndBlock, + dcr->Copy, dcr->Stripe, + edit_uint64(dcr->VolMediaId, ed1)); + } + Dmsg1(100, ">dird %s", dir->msg); if (dir->recv() <= 0) { Dmsg0(190, "create_jobmedia error bnet_recv\n"); Jmsg(jcr, M_FATAL, 0, _("Error creating JobMedia record: ERR=%s\n"), @@ -417,8 +440,21 @@ bool dir_create_jobmedia_record(DCR *dcr) } -/* +/** * Update File Attribute data + * We do the following: + * 1. expand the bsock buffer to be large enough + * 2. Write a "header" into the buffer with serialized data + * VolSessionId + * VolSeesionTime + * FileIndex + * Stream + * data length that follows + * start of raw byte data from the Device record. + * Note, this is primarily for Attribute data, but can + * also handle any device record. The Director must know + * the raw byte data format that is defined for each Stream. + * Now Restore Objects pass through here STREAM_RESTORE_OBJECT */ bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec) { @@ -443,11 +479,15 @@ bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec) ser_bytes(rec->data, rec->data_len); dir->msglen = ser_length(dir->msg); Dmsg1(1800, ">dird %s\n", dir->msg); /* Attributes */ + if (rec->Stream == STREAM_UNIX_ATTRIBUTES || + rec->Stream == STREAM_UNIX_ATTRIBUTES_EX) { + dir->set_data_end(); /* set offset of last valid data */ + } return dir->send(); } -/* +/** * Request the sysop to create an appendable volume * * Entered with device blocked. @@ -472,6 +512,9 @@ bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr) JCR *jcr = dcr->jcr; bool got_vol = false; + if (job_canceled(jcr)) { + return false; + } Dmsg0(400, "enter dir_ask_sysop_to_create_appendable_volume\n"); ASSERT(dev->blocked()); for ( ;; ) { @@ -482,16 +525,14 @@ bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr) Jmsg(jcr, M_INFO, 0, "%s", dev->errmsg); return false; } - dev->dlock(); got_vol = dir_find_next_appendable_volume(dcr); /* get suggested volume */ - dev->dunlock(); if (got_vol) { - return true; + goto get_out; } else { if (stat == W_TIMEOUT || stat == W_MOUNT) { - Jmsg(jcr, M_MOUNT, 0, _( -"Job %s waiting. Cannot find any appendable volumes.\n" -"Please use the \"label\" command to create a new Volume for:\n" + Mmsg(dev->errmsg, _( +"Job %s is waiting. Cannot find any appendable volumes.\n" +"Please use the \"label\" command to create a new Volume for:\n" " Storage: %s\n" " Pool: %s\n" " Media type: %s\n"), @@ -499,6 +540,8 @@ bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr) dev->print_name(), dcr->pool_name, dcr->media_type); + Jmsg(jcr, M_MOUNT, 0, "%s", dev->errmsg); + Dmsg1(100, "%s", dev->errmsg); } } @@ -530,13 +573,15 @@ bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr) } Dmsg1(100, "Someone woke me for device %s\n", dev->print_name()); } + +get_out: set_jcr_job_status(jcr, JS_Running); dir_send_job_status(jcr); Dmsg0(100, "leave dir_ask_sysop_to_mount_create_appendable_volume\n"); return true; } -/* +/** * Request to mount specific Volume * * Entered with device blocked and dcr->VolumeName is desired @@ -609,7 +654,7 @@ bool dir_ask_sysop_to_mount_volume(DCR *dcr, int mode) if (dev->poll) { Dmsg1(400, "Poll timeout in mount vol on device %s\n", dev->print_name()); Dmsg1(400, "Blocked=%s\n", dev->print_blocked()); - goto bail_out; + goto get_out; } if (stat == W_TIMEOUT) { @@ -632,7 +677,7 @@ bool dir_ask_sysop_to_mount_volume(DCR *dcr, int mode) break; } -bail_out: +get_out: set_jcr_job_status(jcr, JS_Running); dir_send_job_status(jcr); Dmsg0(400, "leave dir_ask_sysop_to_mount_volume\n");