X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fdird%2Fbsr.c;h=2b2e77526e362bdc9e5be97118da1d7ab64b9203;hb=3f8a3a045ea058657030f588a10f786449d00e0d;hp=f656817ee19ff63624600f010cd3f5f3e57a3f4e;hpb=20ea6e850c589bc5deb55a6de373ba1c3b5d6eb5;p=bacula%2Fbacula diff --git a/bacula/src/dird/bsr.c b/bacula/src/dird/bsr.c index f656817ee1..2b2e77526e 100644 --- a/bacula/src/dird/bsr.c +++ b/bacula/src/dird/bsr.c @@ -11,22 +11,17 @@ */ /* - Copyright (C) 2002-2005 Kern Sibbald + Copyright (C) 2002-2006 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. + modify it under the terms of the GNU General Public License + version 2 as amended with additional clauses defined in the + file LICENSE in the main source directory. 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. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + the file LICENSE for additional details. */ @@ -34,7 +29,7 @@ #include "dird.h" /* Forward referenced functions */ -static uint32_t write_bsr(UAContext *ua, RBSR *bsr, FILE *fd); +static uint32_t write_bsr(UAContext *ua, RESTORE_CTX &rx, FILE *fd); void print_bsr(UAContext *ua, RBSR *bsr); @@ -51,12 +46,34 @@ RBSR_FINDEX *new_findex() /* Free all BSR FileIndex entries */ static void free_findex(RBSR_FINDEX *fi) { - if (fi) { - free_findex(fi->next); + RBSR_FINDEX *next; + for ( ; fi; fi=next) { + next = fi->next; free(fi); } } +/* + * Get storage device name from Storage resource + */ +static bool get_storage_device(char *device, char *storage) +{ + STORE *store; + if (storage[0] == 0) { + return false; + } + store = (STORE *)GetResWithName(R_STORAGE, storage); + if (!store) { + return false; + } + DEVICE *dev = (DEVICE *)(store->device->first()); + if (!dev) { + return false; + } + bstrncpy(device, dev->hdr.name, MAX_NAME_LENGTH); + return true; +} + /* * Our data structures were not designed completely * correctly, so the file indexes cover the full @@ -115,10 +132,10 @@ static void print_findex(UAContext *ua, RBSR_FINDEX *fi) for ( ; fi; fi=fi->next) { if (fi->findex == fi->findex2) { bsendmsg(ua, "FileIndex=%d\n", fi->findex); -// Dmsg1(100, "FileIndex=%d\n", fi->findex); + Dmsg1(1000, "FileIndex=%d\n", fi->findex); } else { bsendmsg(ua, "FileIndex=%d-%d\n", fi->findex, fi->findex2); -// Dmsg2(100, "FileIndex=%d-%d\n", fi->findex, fi->findex2); + Dmsg2(1000, "FileIndex=%d-%d\n", fi->findex, fi->findex2); } } } @@ -134,12 +151,13 @@ RBSR *new_bsr() /* Free the entire BSR */ void free_bsr(RBSR *bsr) { - if (bsr) { + RBSR *next; + for ( ; bsr; bsr=next) { free_findex(bsr->fi); if (bsr->VolParams) { free(bsr->VolParams); } - free_bsr(bsr->next); + next = bsr->next; free(bsr); } } @@ -148,15 +166,15 @@ void free_bsr(RBSR *bsr) * Complete the BSR by filling in the VolumeName and * VolSessionId and VolSessionTime using the JobId */ -int complete_bsr(UAContext *ua, RBSR *bsr) +bool complete_bsr(UAContext *ua, RBSR *bsr) { - if (bsr) { + for ( ; bsr; bsr=bsr->next) { JOB_DBR jr; memset(&jr, 0, sizeof(jr)); jr.JobId = bsr->JobId; if (!db_get_job_record(ua->jcr, ua->db, &jr)) { bsendmsg(ua, _("Unable to get Job record. ERR=%s\n"), db_strerror(ua->db)); - return 0; + return false; } bsr->VolSessionId = jr.VolSessionId; bsr->VolSessionTime = jr.VolSessionTime; @@ -167,24 +185,48 @@ int complete_bsr(UAContext *ua, RBSR *bsr) free(bsr->VolParams); bsr->VolParams = NULL; } - return 0; + return false; } - return complete_bsr(ua, bsr->next); } - return 1; + return true; +} + +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +static uint32_t uniq = 0; + +void make_unique_restore_filename(UAContext *ua, POOLMEM **fname) +{ + JCR *jcr = ua->jcr; + int i = find_arg_with_value(ua, "bootstrap"); + if (i >= 0) { + Mmsg(fname, "%s", ua->argv[i]); + jcr->unlink_bsr = false; + } else { + P(mutex); + uniq++; + V(mutex); + Mmsg(fname, "%s/%s.restore.%u.bsr", working_directory, my_name, uniq); + jcr->unlink_bsr = true; + } + if (jcr->RestoreBootstrap) { + free(jcr->RestoreBootstrap); + } + jcr->RestoreBootstrap = bstrdup(*fname); } /* * Write the bootstrap records to file */ -uint32_t write_bsr_file(UAContext *ua, RBSR *bsr) +uint32_t write_bsr_file(UAContext *ua, RESTORE_CTX &rx) { FILE *fd; POOLMEM *fname = get_pool_memory(PM_MESSAGE); uint32_t count = 0;; bool err; + char *p; + JobId_t JobId; - Mmsg(fname, "%s/restore.bsr", working_directory); + make_unique_restore_filename(ua, &fname); fd = fopen(fname, "w+"); if (!fd) { berrno be; @@ -193,7 +235,7 @@ uint32_t write_bsr_file(UAContext *ua, RBSR *bsr) goto bail_out; } /* Write them to file */ - count = write_bsr(ua, bsr, fd); + count = write_bsr(ua, rx, fd); err = ferror(fd); fclose(fd); if (err) { @@ -210,10 +252,27 @@ uint32_t write_bsr_file(UAContext *ua, RBSR *bsr) bsendmsg(ua, _("The job will require the following Volumes:\n")); /* Create Unique list of Volumes using prompt list */ start_prompt(ua, ""); - for (RBSR *nbsr=bsr; nbsr; nbsr=nbsr->next) { - for (int i=0; i < nbsr->VolCount; i++) { - if (nbsr->VolParams[i].VolumeName[0]) { - add_prompt(ua, nbsr->VolParams[i].VolumeName); + if (*rx.JobIds) { + /* Ensure that the volumes are printed in JobId order */ + for (p=rx.JobIds; get_next_jobid_from_list(&p, &JobId) > 0; ) { + for (RBSR *nbsr=rx.bsr; nbsr; nbsr=nbsr->next) { + if (JobId != nbsr->JobId) { + continue; + } + for (int i=0; i < nbsr->VolCount; i++) { + if (nbsr->VolParams[i].VolumeName[0]) { + add_prompt(ua, nbsr->VolParams[i].VolumeName); + } + } + } + } + } else { + /* Print Volumes in any order */ + for (RBSR *nbsr=rx.bsr; nbsr; nbsr=nbsr->next) { + for (int i=0; i < nbsr->VolCount; i++) { + if (nbsr->VolParams[i].VolumeName[0]) { + add_prompt(ua, nbsr->VolParams[i].VolumeName); + } } } } @@ -233,66 +292,144 @@ bail_out: return count; } -static uint32_t write_bsr(UAContext *ua, RBSR *bsr, FILE *fd) +/* + * Here we actually write out the details of the bsr file. + * Note, there is one bsr for each JobId, but the bsr may + * have multiple volumes, which have been entered in the + * order they were written. + * The bsrs must be written out in the order the JobIds + * are found in the jobid list. + */ +static uint32_t write_bsr(UAContext *ua, RESTORE_CTX &rx, FILE *fd) { uint32_t count = 0; uint32_t total_count = 0; uint32_t LastIndex = 0; bool first = true; - if (bsr) { - /* - * For a given volume, loop over all the JobMedia records. - * VolCount is the number of JobMedia records. - */ - for (int i=0; i < bsr->VolCount; i++) { - if (!is_volume_selected(bsr->fi, bsr->VolParams[i].FirstIndex, - bsr->VolParams[i].LastIndex)) { - bsr->VolParams[i].VolumeName[0] = 0; /* zap VolumeName */ - continue; - } - fprintf(fd, "Volume=\"%s\"\n", bsr->VolParams[i].VolumeName); - fprintf(fd, "MediaType=\"%s\"\n", bsr->VolParams[i].MediaType); - fprintf(fd, "VolSessionId=%u\n", bsr->VolSessionId); - fprintf(fd, "VolSessionTime=%u\n", bsr->VolSessionTime); - if (bsr->VolParams[i].StartFile == bsr->VolParams[i].EndFile) { - fprintf(fd, "VolFile=%u\n", bsr->VolParams[i].StartFile); - } else { - fprintf(fd, "VolFile=%u-%u\n", bsr->VolParams[i].StartFile, - bsr->VolParams[i].EndFile); - } - if (bsr->VolParams[i].StartBlock == bsr->VolParams[i].EndBlock) { - fprintf(fd, "VolFile=%u\n", bsr->VolParams[i].StartBlock); - } else { - fprintf(fd, "VolBlock=%u-%u\n", bsr->VolParams[i].StartBlock, - bsr->VolParams[i].EndBlock); + char *p; + JobId_t JobId; + char device[MAX_NAME_LENGTH]; + RBSR *bsr; + if (*rx.JobIds == 0) { + for (bsr=rx.bsr; bsr; bsr=bsr->next) { + /* + * For a given volume, loop over all the JobMedia records. + * VolCount is the number of JobMedia records. + */ + for (int i=0; i < bsr->VolCount; i++) { + if (!is_volume_selected(bsr->fi, bsr->VolParams[i].FirstIndex, + bsr->VolParams[i].LastIndex)) { + bsr->VolParams[i].VolumeName[0] = 0; /* zap VolumeName */ + continue; + } + fprintf(fd, "Volume=\"%s\"\n", bsr->VolParams[i].VolumeName); + fprintf(fd, "MediaType=\"%s\"\n", bsr->VolParams[i].MediaType); + if (get_storage_device(device, bsr->VolParams[i].Storage)) { + fprintf(fd, "Device=\"%s\"\n", device); + } + if (bsr->VolParams[i].Slot > 0) { + fprintf(fd, "Slot=%d\n", bsr->VolParams[i].Slot); + } + fprintf(fd, "VolSessionId=%u\n", bsr->VolSessionId); + fprintf(fd, "VolSessionTime=%u\n", bsr->VolSessionTime); + if (bsr->VolParams[i].StartFile == bsr->VolParams[i].EndFile) { + fprintf(fd, "VolFile=%u\n", bsr->VolParams[i].StartFile); + } else { + fprintf(fd, "VolFile=%u-%u\n", bsr->VolParams[i].StartFile, + bsr->VolParams[i].EndFile); + } + if (bsr->VolParams[i].StartBlock == bsr->VolParams[i].EndBlock) { + fprintf(fd, "VolBlock=%u\n", bsr->VolParams[i].StartBlock); + } else { + fprintf(fd, "VolBlock=%u-%u\n", bsr->VolParams[i].StartBlock, + bsr->VolParams[i].EndBlock); + } + // Dmsg2(100, "bsr VolParam FI=%u LI=%u\n", + // bsr->VolParams[i].FirstIndex, bsr->VolParams[i].LastIndex); + + count = write_findex(ua, bsr->fi, bsr->VolParams[i].FirstIndex, + bsr->VolParams[i].LastIndex, fd); + if (count) { + fprintf(fd, "Count=%u\n", count); + } + total_count += count; + /* If the same file is present on two tapes or in two files + * on a tape, it is a continuation, and should not be treated + * twice in the totals. + */ + if (!first && LastIndex == bsr->VolParams[i].FirstIndex) { + total_count--; + } + first = false; + LastIndex = bsr->VolParams[i].LastIndex; } -// Dmsg2(100, "bsr VolParam FI=%u LI=%u\n", -// bsr->VolParams[i].FirstIndex, bsr->VolParams[i].LastIndex); - - count = write_findex(ua, bsr->fi, bsr->VolParams[i].FirstIndex, - bsr->VolParams[i].LastIndex, fd); - if (count) { - fprintf(fd, "Count=%u\n", count); + } + return total_count; + } + for (p=rx.JobIds; get_next_jobid_from_list(&p, &JobId) > 0; ) { + for (bsr=rx.bsr; bsr; bsr=bsr->next) { + if (JobId != bsr->JobId) { + continue; } - total_count += count; - /* If the same file is present on two tapes or in two files - * on a tape, it is a continuation, and should not be treated - * twice in the totals. + /* + * For a given volume, loop over all the JobMedia records. + * VolCount is the number of JobMedia records. */ - if (!first && LastIndex == bsr->VolParams[i].FirstIndex) { - total_count--; + for (int i=0; i < bsr->VolCount; i++) { + if (!is_volume_selected(bsr->fi, bsr->VolParams[i].FirstIndex, + bsr->VolParams[i].LastIndex)) { + bsr->VolParams[i].VolumeName[0] = 0; /* zap VolumeName */ + continue; + } + fprintf(fd, "Volume=\"%s\"\n", bsr->VolParams[i].VolumeName); + fprintf(fd, "MediaType=\"%s\"\n", bsr->VolParams[i].MediaType); + if (get_storage_device(device, bsr->VolParams[i].Storage)) { + fprintf(fd, "Device=\"%s\"\n", device); + } + if (bsr->VolParams[i].Slot > 0) { + fprintf(fd, "Slot=%d\n", bsr->VolParams[i].Slot); + } + fprintf(fd, "VolSessionId=%u\n", bsr->VolSessionId); + fprintf(fd, "VolSessionTime=%u\n", bsr->VolSessionTime); + if (bsr->VolParams[i].StartFile == bsr->VolParams[i].EndFile) { + fprintf(fd, "VolFile=%u\n", bsr->VolParams[i].StartFile); + } else { + fprintf(fd, "VolFile=%u-%u\n", bsr->VolParams[i].StartFile, + bsr->VolParams[i].EndFile); + } + if (bsr->VolParams[i].StartBlock == bsr->VolParams[i].EndBlock) { + fprintf(fd, "VolBlock=%u\n", bsr->VolParams[i].StartBlock); + } else { + fprintf(fd, "VolBlock=%u-%u\n", bsr->VolParams[i].StartBlock, + bsr->VolParams[i].EndBlock); + } + // Dmsg2(100, "bsr VolParam FI=%u LI=%u\n", + // bsr->VolParams[i].FirstIndex, bsr->VolParams[i].LastIndex); + + count = write_findex(ua, bsr->fi, bsr->VolParams[i].FirstIndex, + bsr->VolParams[i].LastIndex, fd); + if (count) { + fprintf(fd, "Count=%u\n", count); + } + total_count += count; + /* If the same file is present on two tapes or in two files + * on a tape, it is a continuation, and should not be treated + * twice in the totals. + */ + if (!first && LastIndex == bsr->VolParams[i].FirstIndex) { + total_count--; + } + first = false; + LastIndex = bsr->VolParams[i].LastIndex; } - first = false; - LastIndex = bsr->VolParams[i].LastIndex; } - write_bsr(ua, bsr->next, fd); } return total_count; } void print_bsr(UAContext *ua, RBSR *bsr) { - if (bsr) { + for ( ; bsr; bsr=bsr->next) { for (int i=0; i < bsr->VolCount; i++) { bsendmsg(ua, "Volume=\"%s\"\n", bsr->VolParams[i].VolumeName); bsendmsg(ua, "MediaType\"%s\"\n", bsr->VolParams[i].MediaType);