X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fstored%2Fspool.c;h=d79b0f08578210ecfa5dbbee02a095d39db77787;hb=9326b2fd753cf4a714d40d5c190ba04b16261510;hp=ac7bd0f3223deda94a0935017e1d3ca5399c57a5;hpb=da8584df92d56dd3cbf3c9a7563b22d8335ba219;p=bacula%2Fbacula diff --git a/bacula/src/stored/spool.c b/bacula/src/stored/spool.c index ac7bd0f322..d79b0f0857 100644 --- a/bacula/src/stored/spool.c +++ b/bacula/src/stored/spool.c @@ -1,27 +1,22 @@ /* * Spooling code * - * Kern Sibbald, March 2004 + * Kern Sibbald, March 2004 * * Version $Id$ */ /* - Copyright (C) 2004-2004 Kern Sibbald and John Walker + Copyright (C) 2004-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. */ @@ -29,9 +24,9 @@ #include "stored.h" /* Forward referenced subroutines */ -static void make_unique_data_spool_filename(JCR *jcr, POOLMEM **name); -static bool open_data_spool_file(JCR *jcr); -static bool close_data_spool_file(JCR *jcr); +static void make_unique_data_spool_filename(DCR *dcr, POOLMEM **name); +static bool open_data_spool_file(DCR *dcr); +static bool close_data_spool_file(DCR *dcr); static bool despool_data(DCR *dcr, bool commit); static int read_block_from_spool_file(DCR *dcr); static bool open_attr_spool_file(JCR *jcr, BSOCK *bs); @@ -40,13 +35,13 @@ static bool write_spool_header(DCR *dcr); static bool write_spool_data(DCR *dcr); struct spool_stats_t { - uint32_t data_jobs; /* current jobs spooling data */ + uint32_t data_jobs; /* current jobs spooling data */ uint32_t attr_jobs; - uint32_t total_data_jobs; /* total jobs to have spooled data */ + uint32_t total_data_jobs; /* total jobs to have spooled data */ uint32_t total_attr_jobs; - int64_t max_data_size; /* max data size */ + int64_t max_data_size; /* max data size */ int64_t max_attr_size; - int64_t data_size; /* current data size (all jobs running) */ + int64_t data_size; /* current data size (all jobs running) */ int64_t attr_size; }; @@ -56,9 +51,9 @@ spool_stats_t spool_stats; /* * Header for data spool record */ struct spool_hdr { - int32_t FirstIndex; /* FirstIndex for buffer */ - int32_t LastIndex; /* LastIndex for buffer */ - uint32_t len; /* length of next buffer */ + int32_t FirstIndex; /* FirstIndex for buffer */ + int32_t LastIndex; /* LastIndex for buffer */ + uint32_t len; /* length of next buffer */ }; enum { @@ -67,93 +62,103 @@ enum { RB_OK }; -void list_spool_stats(BSOCK *bs) +void list_spool_stats(void sendit(const char *msg, int len, void *sarg), void *arg) { - char ed1[30], ed2[30]; + char *msg, ed1[30], ed2[30]; + int len; + + msg = (char *)get_pool_memory(PM_MESSAGE); + if (spool_stats.data_jobs || spool_stats.max_data_size) { - bnet_fsend(bs, "Data spooling: %u active jobs, %s bytes; %u total jobs, %s max bytes/job.\n", - spool_stats.data_jobs, edit_uint64_with_commas(spool_stats.data_size, ed1), - spool_stats.total_data_jobs, - edit_uint64_with_commas(spool_stats.max_data_size, ed2)); + len = Mmsg(msg, _("Data spooling: %u active jobs, %s bytes; %u total jobs, %s max bytes/job.\n"), + spool_stats.data_jobs, edit_uint64_with_commas(spool_stats.data_size, ed1), + spool_stats.total_data_jobs, + edit_uint64_with_commas(spool_stats.max_data_size, ed2)); + + sendit(msg, len, arg); } if (spool_stats.attr_jobs || spool_stats.max_attr_size) { - bnet_fsend(bs, "Attr spooling: %u active jobs, %s bytes; %u total jobs, %s max bytes.\n", - spool_stats.attr_jobs, edit_uint64_with_commas(spool_stats.attr_size, ed1), - spool_stats.total_attr_jobs, - edit_uint64_with_commas(spool_stats.max_attr_size, ed2)); + len = Mmsg(msg, _("Attr spooling: %u active jobs, %s bytes; %u total jobs, %s max bytes.\n"), + spool_stats.attr_jobs, edit_uint64_with_commas(spool_stats.attr_size, ed1), + spool_stats.total_attr_jobs, + edit_uint64_with_commas(spool_stats.max_attr_size, ed2)); + + sendit(msg, len, arg); } + + free_pool_memory(msg); } -bool begin_data_spool(JCR *jcr) +bool begin_data_spool(DCR *dcr) { bool stat = true; - if (jcr->spool_data) { + if (!dcr->dev->is_dvd() && dcr->jcr->spool_data) { Dmsg0(100, "Turning on data spooling\n"); - jcr->dcr->spool_data = true; - stat = open_data_spool_file(jcr); + dcr->spool_data = true; + stat = open_data_spool_file(dcr); if (stat) { - jcr->dcr->spooling = true; - Jmsg(jcr, M_INFO, 0, _("Spooling data ...\n")); - P(mutex); - spool_stats.data_jobs++; - V(mutex); + dcr->spooling = true; + Jmsg(dcr->jcr, M_INFO, 0, _("Spooling data ...\n")); + P(mutex); + spool_stats.data_jobs++; + V(mutex); } } return stat; } -bool discard_data_spool(JCR *jcr) +bool discard_data_spool(DCR *dcr) { - if (jcr->dcr->spooling) { + if (dcr->spooling) { Dmsg0(100, "Data spooling discarded\n"); - return close_data_spool_file(jcr); + return close_data_spool_file(dcr); } return true; } -bool commit_data_spool(JCR *jcr) +bool commit_data_spool(DCR *dcr) { bool stat; - if (jcr->dcr->spooling) { + if (dcr->spooling) { Dmsg0(100, "Committing spooled data\n"); - stat = despool_data(jcr->dcr, true /*commit*/); + stat = despool_data(dcr, true /*commit*/); if (!stat) { - Pmsg1(000, "Bad return from despool WroteVol=%d\n", jcr->dcr->WroteVol); - close_data_spool_file(jcr); - return false; + Dmsg1(100, _("Bad return from despool WroteVol=%d\n"), dcr->WroteVol); + close_data_spool_file(dcr); + return false; } - return close_data_spool_file(jcr); + return close_data_spool_file(dcr); } return true; } -static void make_unique_data_spool_filename(JCR *jcr, POOLMEM **name) +static void make_unique_data_spool_filename(DCR *dcr, POOLMEM **name) { const char *dir; - if (jcr->dcr->dev->device->spool_directory) { - dir = jcr->dcr->dev->device->spool_directory; + if (dcr->dev->device->spool_directory) { + dir = dcr->dev->device->spool_directory; } else { dir = working_directory; } - Mmsg(name, "%s/%s.data.spool.%s.%s", dir, my_name, jcr->Job, - jcr->dcr->device->hdr.name); + Mmsg(name, "%s/%s.data.%s.%s.spool", dir, my_name, dcr->jcr->Job, + dcr->device->hdr.name); } -static bool open_data_spool_file(JCR *jcr) +static bool open_data_spool_file(DCR *dcr) { POOLMEM *name = get_pool_memory(PM_MESSAGE); int spool_fd; - make_unique_data_spool_filename(jcr, &name); + make_unique_data_spool_filename(dcr, &name); if ((spool_fd = open(name, O_CREAT|O_TRUNC|O_RDWR|O_BINARY, 0640)) >= 0) { - jcr->dcr->spool_fd = spool_fd; - jcr->spool_attributes = true; + dcr->spool_fd = spool_fd; + dcr->jcr->spool_attributes = true; } else { berrno be; - Jmsg(jcr, M_FATAL, 0, _("Open data spool file %s failed: ERR=%s\n"), name, - be.strerror()); + Jmsg(dcr->jcr, M_FATAL, 0, _("Open data spool file %s failed: ERR=%s\n"), name, + be.strerror()); free_pool_memory(name); return false; } @@ -162,25 +167,25 @@ static bool open_data_spool_file(JCR *jcr) return true; } -static bool close_data_spool_file(JCR *jcr) +static bool close_data_spool_file(DCR *dcr) { POOLMEM *name = get_pool_memory(PM_MESSAGE); P(mutex); spool_stats.data_jobs--; spool_stats.total_data_jobs++; - if (spool_stats.data_size < jcr->dcr->spool_size) { + if (spool_stats.data_size < dcr->job_spool_size) { spool_stats.data_size = 0; } else { - spool_stats.data_size -= jcr->dcr->spool_size; + spool_stats.data_size -= dcr->job_spool_size; } - jcr->dcr->spool_size = 0; + dcr->job_spool_size = 0; V(mutex); - make_unique_data_spool_filename(jcr, &name); - close(jcr->dcr->spool_fd); - jcr->dcr->spool_fd = -1; - jcr->dcr->spooling = false; + make_unique_data_spool_filename(dcr, &name); + close(dcr->spool_fd); + dcr->spool_fd = -1; + dcr->spooling = false; unlink(name); Dmsg1(100, "Deleted spool file: %s\n", name); free_pool_memory(name); @@ -200,11 +205,23 @@ static bool despool_data(DCR *dcr, bool commit) char ec1[50]; Dmsg0(100, "Despooling data\n"); - Jmsg(jcr, M_INFO, 0, _("%s spooled data to Volume. Despooling %s bytes ...\n"), - commit?"Committing":"Writing", - edit_uint64_with_commas(jcr->dcr->spool_size, ec1)); + /* Commit means that the job is done, so we commit, otherwise, we + * are despooling because of user spool size max or some error + * (e.g. filesystem full). + */ + if (commit) { + Jmsg(jcr, M_INFO, 0, _("Committing spooled data to Volume \"%s\". Despooling %s bytes ...\n"), + jcr->dcr->VolumeName, + edit_uint64_with_commas(jcr->dcr->job_spool_size, ec1)); + } else { + Jmsg(jcr, M_INFO, 0, _("Writing spooled data to Volume. Despooling %s bytes ...\n"), + edit_uint64_with_commas(jcr->dcr->job_spool_size, ec1)); + } + dcr->despool_wait = true; dcr->spooling = false; lock_device(dcr->dev); + dcr->despool_wait = false; + dcr->despooling = true; dcr->dev_locked = true; /* @@ -223,49 +240,68 @@ static bool despool_data(DCR *dcr, bool commit) rdev->device = dcr->dev->device; rdcr = new_dcr(NULL, rdev); rdcr->spool_fd = dcr->spool_fd; - rdcr->jcr = jcr; /* set a valid jcr */ - block = dcr->block; /* save block */ - dcr->block = rdcr->block; /* make read and write block the same */ + rdcr->jcr = jcr; /* set a valid jcr */ + block = dcr->block; /* save block */ + dcr->block = rdcr->block; /* make read and write block the same */ Dmsg1(800, "read/write block size = %d\n", block->buf_len); lseek(rdcr->spool_fd, 0, SEEK_SET); /* rewind */ + /* Add run time, to get current wait time */ + time_t despool_start = time(NULL) - jcr->run_time; + for ( ; ok; ) { if (job_canceled(jcr)) { - ok = false; - break; + ok = false; + break; } stat = read_block_from_spool_file(rdcr); if (stat == RB_EOT) { - break; + break; } else if (stat == RB_ERROR) { - ok = false; - break; + ok = false; + break; } ok = write_block_to_device(dcr); + if (!ok) { + Jmsg2(jcr, M_FATAL, 0, _("Fatal append error on device %s: ERR=%s\n"), + dcr->dev->print_name(), dcr->dev->bstrerror()); + } Dmsg3(800, "Write block ok=%d FI=%d LI=%d\n", ok, block->FirstIndex, block->LastIndex); } - dcr->block = block; /* reset block */ + + /* Subtracting run_time give us elapsed time - wait_time since we started despooling */ + time_t despool_elapsed = time(NULL) - despool_start - jcr->run_time; + + if (despool_elapsed <= 0) { + despool_elapsed = 1; + } + + Jmsg(dcr->jcr, M_INFO, 0, _("Despooling elapsed time = %02d:%02d:%02d, Transfer rate = %s bytes/second\n"), + despool_elapsed / 3600, despool_elapsed % 3600 / 60, despool_elapsed % 60, + edit_uint64_with_suffix(jcr->dcr->job_spool_size / despool_elapsed, ec1)); + + dcr->block = block; /* reset block */ lseek(rdcr->spool_fd, 0, SEEK_SET); /* rewind */ if (ftruncate(rdcr->spool_fd, 0) != 0) { berrno be; Jmsg(dcr->jcr, M_ERROR, 0, _("Ftruncate spool file failed: ERR=%s\n"), - be.strerror()); - Pmsg1(000, "Bad return from ftruncate. ERR=%s\n", be.strerror()); + be.strerror()); + Pmsg1(000, _("Bad return from ftruncate. ERR=%s\n"), be.strerror()); ok = false; } P(mutex); - if (spool_stats.data_size < dcr->spool_size) { + if (spool_stats.data_size < dcr->job_spool_size) { spool_stats.data_size = 0; } else { - spool_stats.data_size -= dcr->spool_size; + spool_stats.data_size -= dcr->job_spool_size; } V(mutex); P(dcr->dev->spool_mutex); - dcr->dev->spool_size -= dcr->spool_size; - dcr->spool_size = 0; /* zap size in input dcr */ + dcr->dev->spool_size -= dcr->job_spool_size; + dcr->job_spool_size = 0; /* zap size in input dcr */ V(dcr->dev->spool_mutex); free_memory(rdev->dev_name); free_pool_memory(rdev->errmsg); @@ -273,9 +309,10 @@ static bool despool_data(DCR *dcr, bool commit) rdcr->jcr = NULL; free_dcr(rdcr); free(rdev); - unlock_device(dcr->dev); dcr->dev_locked = false; - dcr->spooling = true; /* turn on spooling again */ + dcr->spooling = true; /* turn on spooling again */ + dcr->despooling = false; + unlock_device(dcr->dev); return ok; } @@ -283,8 +320,8 @@ static bool despool_data(DCR *dcr, bool commit) * Read a block from the spool file * * Returns RB_OK on success - * RB_EOT when file done - * RB_ERROR on error + * RB_EOT when file done + * RB_ERROR on error */ static int read_block_from_spool_file(DCR *dcr) { @@ -300,25 +337,25 @@ static int read_block_from_spool_file(DCR *dcr) return RB_EOT; } else if (stat != (ssize_t)rlen) { if (stat == -1) { - berrno be; + berrno be; Jmsg(dcr->jcr, M_FATAL, 0, _("Spool header read error. ERR=%s\n"), - be.strerror()); + be.strerror()); } else { - Pmsg2(000, "Spool read error. Wanted %u bytes, got %u\n", rlen, stat); - Jmsg2(dcr->jcr, M_FATAL, 0, _("Spool header read error. Wanted %u bytes, got %u\n"), rlen, stat); + Pmsg2(000, _("Spool read error. Wanted %u bytes, got %d\n"), rlen, stat); + Jmsg2(dcr->jcr, M_FATAL, 0, _("Spool header read error. Wanted %u bytes, got %d\n"), rlen, stat); } return RB_ERROR; } rlen = hdr.len; if (rlen > block->buf_len) { - Pmsg2(000, "Spool block too big. Max %u bytes, got %u\n", block->buf_len, rlen); + Pmsg2(000, _("Spool block too big. Max %u bytes, got %u\n"), block->buf_len, rlen); Jmsg2(dcr->jcr, M_FATAL, 0, _("Spool block too big. Max %u bytes, got %u\n"), block->buf_len, rlen); return RB_ERROR; } stat = read(dcr->spool_fd, (char *)block->buf, (size_t)rlen); if (stat != (ssize_t)rlen) { - Pmsg2(000, "Spool data read error. Wanted %u bytes, got %u\n", rlen, stat); - Jmsg2(dcr->jcr, M_FATAL, 0, _("Spool data read error. Wanted %u bytes, got %u\n"), rlen, stat); + Pmsg2(000, _("Spool data read error. Wanted %u bytes, got %d\n"), rlen, stat); + Jmsg2(dcr->jcr, M_FATAL, 0, _("Spool data read error. Wanted %u bytes, got %d\n"), rlen, stat); return RB_ERROR; } /* Setup write pointers */ @@ -336,25 +373,25 @@ static int read_block_from_spool_file(DCR *dcr) * Write a block to the spool file * * Returns: true on success or EOT - * false on hard error + * false on hard error */ bool write_block_to_spool_file(DCR *dcr) { - uint32_t wlen, hlen; /* length to write */ + uint32_t wlen, hlen; /* length to write */ bool despool = false; DEV_BLOCK *block = dcr->block; ASSERT(block->binbuf == ((uint32_t) (block->bufp - block->buf))); - if (block->binbuf <= WRITE_BLKHDR_LENGTH) { /* Does block have data in it? */ + if (block->binbuf <= WRITE_BLKHDR_LENGTH) { /* Does block have data in it? */ return true; } hlen = sizeof(spool_hdr); wlen = block->binbuf; P(dcr->dev->spool_mutex); - dcr->spool_size += hlen + wlen; + dcr->job_spool_size += hlen + wlen; dcr->dev->spool_size += hlen + wlen; - if ((dcr->max_spool_size > 0 && dcr->spool_size >= dcr->max_spool_size) || + if ((dcr->max_job_spool_size > 0 && dcr->job_spool_size >= dcr->max_job_spool_size) || (dcr->dev->max_spool_size > 0 && dcr->dev->spool_size >= dcr->dev->max_spool_size)) { despool = true; } @@ -370,19 +407,19 @@ bool write_block_to_spool_file(DCR *dcr) char ec1[30], ec2[30], ec3[30], ec4[30]; Dmsg4(100, "Despool in write_block_to_spool_file max_size=%s size=%s " "max_job_size=%s job_size=%s\n", - edit_uint64_with_commas(dcr->max_spool_size, ec1), - edit_uint64_with_commas(dcr->spool_size, ec2), - edit_uint64_with_commas(dcr->dev->max_spool_size, ec3), - edit_uint64_with_commas(dcr->dev->spool_size, ec4)); + edit_uint64_with_commas(dcr->max_job_spool_size, ec1), + edit_uint64_with_commas(dcr->job_spool_size, ec2), + edit_uint64_with_commas(dcr->dev->max_spool_size, ec3), + edit_uint64_with_commas(dcr->dev->spool_size, ec4)); #endif Jmsg(dcr->jcr, M_INFO, 0, _("User specified spool size reached.\n")); if (!despool_data(dcr, false)) { - Pmsg0(000, "Bad return from despool in write_block.\n"); - return false; + Pmsg0(000, _("Bad return from despool in write_block.\n")); + return false; } /* Despooling cleared these variables so reset them */ P(dcr->dev->spool_mutex); - dcr->spool_size += hlen + wlen; + dcr->job_spool_size += hlen + wlen; dcr->dev->spool_size += hlen + wlen; V(dcr->dev->spool_mutex); Jmsg(dcr->jcr, M_INFO, 0, _("Spooling data again ...\n")); @@ -415,25 +452,25 @@ static bool write_spool_header(DCR *dcr) for (int retry=0; retry<=1; retry++) { stat = write(dcr->spool_fd, (char*)&hdr, sizeof(hdr)); if (stat == -1) { - berrno be; + berrno be; Jmsg(dcr->jcr, M_FATAL, 0, _("Error writing header to spool file. ERR=%s\n"), - be.strerror()); + be.strerror()); } if (stat != (ssize_t)sizeof(hdr)) { - /* If we wrote something, truncate it, then despool */ - if (stat != -1) { - if (ftruncate(dcr->spool_fd, lseek(dcr->spool_fd, (off_t)0, SEEK_CUR) - stat) != 0) { - berrno be; + /* If we wrote something, truncate it, then despool */ + if (stat != -1) { + if (ftruncate(dcr->spool_fd, lseek(dcr->spool_fd, (off_t)0, SEEK_CUR) - stat) != 0) { + berrno be; Jmsg(dcr->jcr, M_FATAL, 0, _("Ftruncate spool file failed: ERR=%s\n"), - be.strerror()); - return false; - } - } - if (!despool_data(dcr, false)) { + be.strerror()); + return false; + } + } + if (!despool_data(dcr, false)) { Jmsg(dcr->jcr, M_FATAL, 0, _("Fatal despooling error.")); - return false; - } - continue; /* try again */ + return false; + } + continue; /* try again */ } return true; } @@ -450,31 +487,31 @@ static bool write_spool_data(DCR *dcr) for (int retry=0; retry<=1; retry++) { stat = write(dcr->spool_fd, block->buf, (size_t)block->binbuf); if (stat == -1) { - berrno be; + berrno be; Jmsg(dcr->jcr, M_FATAL, 0, _("Error writing data to spool file. ERR=%s\n"), - be.strerror()); + be.strerror()); } if (stat != (ssize_t)block->binbuf) { - /* - * If we wrote something, truncate it and the header, then despool - */ - if (stat != -1) { - if (ftruncate(dcr->spool_fd, lseek(dcr->spool_fd, (off_t)0, SEEK_CUR) - - stat - sizeof(spool_hdr)) != 0) { - berrno be; + /* + * If we wrote something, truncate it and the header, then despool + */ + if (stat != -1) { + if (ftruncate(dcr->spool_fd, lseek(dcr->spool_fd, (off_t)0, SEEK_CUR) + - stat - sizeof(spool_hdr)) != 0) { + berrno be; Jmsg(dcr->jcr, M_FATAL, 0, _("Ftruncate spool file failed: ERR=%s\n"), - be.strerror()); - return false; - } - } - if (!despool_data(dcr, false)) { + be.strerror()); + return false; + } + } + if (!despool_data(dcr, false)) { Jmsg(dcr->jcr, M_FATAL, 0, _("Fatal despooling error.")); - return false; - } - if (!write_spool_header(dcr)) { - return false; - } - continue; /* try again */ + return false; + } + if (!write_spool_header(dcr)) { + return false; + } + continue; /* try again */ } return true; } @@ -517,9 +554,9 @@ static void update_attr_spool_size(ssize_t size) P(mutex); if (size > 0) { if ((spool_stats.attr_size - size) > 0) { - spool_stats.attr_size -= size; + spool_stats.attr_size -= size; } else { - spool_stats.attr_size = 0; + spool_stats.attr_size = 0; } } V(mutex); @@ -527,35 +564,44 @@ static void update_attr_spool_size(ssize_t size) bool commit_attribute_spool(JCR *jcr) { - ssize_t size; + off_t size; char ec1[30]; if (are_attributes_spooled(jcr)) { - if (fseek(jcr->dir_bsock->spool_fd, 0, SEEK_END) != 0) { - berrno be; + if (fseeko(jcr->dir_bsock->spool_fd, 0, SEEK_END) != 0) { + berrno be; + Jmsg(jcr, M_FATAL, 0, _("Fseek on attributes file failed: ERR=%s\n"), + be.strerror()); + goto bail_out; + } + size = ftello(jcr->dir_bsock->spool_fd); + if (size < 0) { + berrno be; Jmsg(jcr, M_FATAL, 0, _("Fseek on attributes file failed: ERR=%s\n"), - be.strerror()); + be.strerror()); + goto bail_out; } - size = ftell(jcr->dir_bsock->spool_fd); P(mutex); - if (size > 0) { - if (spool_stats.attr_size + size > spool_stats.max_attr_size) { - spool_stats.max_attr_size = spool_stats.attr_size + size; - } + if (spool_stats.attr_size + size > spool_stats.max_attr_size) { + spool_stats.max_attr_size = spool_stats.attr_size + size; } spool_stats.attr_size += size; V(mutex); Jmsg(jcr, M_INFO, 0, _("Sending spooled attrs to the Director. Despooling %s bytes ...\n"), - edit_uint64_with_commas(size, ec1)); + edit_uint64_with_commas(size, ec1)); bnet_despool_to_bsock(jcr->dir_bsock, update_attr_spool_size, size); return close_attr_spool_file(jcr, jcr->dir_bsock); } return true; + +bail_out: + close_attr_spool_file(jcr, jcr->dir_bsock); + return false; } static void make_unique_spool_filename(JCR *jcr, POOLMEM **name, int fd) { - Mmsg(name, "%s/%s.attr.spool.%s.%d", working_directory, my_name, + Mmsg(name, "%s/%s.attr.%s.%d.spool", working_directory, my_name, jcr->Job, fd); } @@ -565,11 +611,11 @@ bool open_attr_spool_file(JCR *jcr, BSOCK *bs) POOLMEM *name = get_pool_memory(PM_MESSAGE); make_unique_spool_filename(jcr, &name, bs->fd); - bs->spool_fd = fopen(name, "w+"); + bs->spool_fd = fopen(name, "w+b"); if (!bs->spool_fd) { berrno be; Jmsg(jcr, M_FATAL, 0, _("fopen attr spool file %s failed: ERR=%s\n"), name, - be.strerror()); + be.strerror()); free_pool_memory(name); return false; }