X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fstored%2Fspool.c;h=0dd49a36d4568bfa4b1155a9924c2df3411717f9;hb=7a8791d4fa5c0d6206a83d735f9636a27c59d652;hp=a9caea326f61e424bdb2972bffcda37dc8f54778;hpb=463df9e4ba74a64f5ae90000e9e6bcdaedbdf4fb;p=bacula%2Fbacula diff --git a/bacula/src/stored/spool.c b/bacula/src/stored/spool.c index a9caea326f..0dd49a36d4 100644 --- a/bacula/src/stored/spool.c +++ b/bacula/src/stored/spool.c @@ -32,10 +32,12 @@ 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 bool despool_data(DCR *dcr); +static bool despool_data(DCR *dcr, bool commit); static int read_block_from_spool_file(DCR *dcr, DEV_BLOCK *block); static bool open_attr_spool_file(JCR *jcr, BSOCK *bs); static bool close_attr_spool_file(JCR *jcr, BSOCK *bs); +static bool write_spool_header(DCR *dcr, DEV_BLOCK *block); +static bool write_spool_data(DCR *dcr, DEV_BLOCK *block); struct spool_stats_t { uint32_t data_jobs; /* current jobs spooling data */ @@ -112,13 +114,10 @@ bool discard_data_spool(JCR *jcr) bool commit_data_spool(JCR *jcr) { bool stat; - char ec1[40]; if (jcr->dcr->spooling) { Dmsg0(100, "Committing spooled data\n"); - Jmsg(jcr, M_INFO, 0, _("Writing spooled data to Volume. Despooling %s bytes ...\n"), - edit_uint64_with_commas(jcr->dcr->dev->spool_size, ec1)); - stat = despool_data(jcr->dcr); + stat = despool_data(jcr->dcr, true /*commit*/); if (!stat) { Dmsg1(000, "Bad return from despool WroteVol=%d\n", jcr->dcr->WroteVol); close_data_spool_file(jcr); @@ -185,7 +184,9 @@ static bool close_data_spool_file(JCR *jcr) return true; } -static bool despool_data(DCR *dcr) +static const char *spool_name = "*spool*"; + +static bool despool_data(DCR *dcr, bool commit) { DEVICE *rdev; DCR *rdcr; @@ -193,17 +194,25 @@ static bool despool_data(DCR *dcr) DEV_BLOCK *block; JCR *jcr = dcr->jcr; int stat; + char ec1[50]; Dmsg0(100, "Despooling data\n"); + Jmsg(jcr, M_INFO, 0, _("%s spooled data to Volume. Despooling %s bytes ...\n"), + commit?"Committing":"Writting", + edit_uint64_with_commas(jcr->dcr->dev->spool_size, ec1)); dcr->spooling = false; lock_device(dcr->dev); dcr->dev_locked = true; - /* Setup a dev structure to read */ + /* + * This is really quite kludgy and should be fixed some time. + * We create a dev structure to read from the spool file + * in rdev and rdcr. + */ rdev = (DEVICE *)malloc(sizeof(DEVICE)); memset(rdev, 0, sizeof(DEVICE)); - rdev->dev_name = get_memory(strlen("spool")+1); - strcpy(rdev->dev_name, "spool"); + rdev->dev_name = get_memory(strlen(spool_name)+1); + strcpy(rdev->dev_name, spool_name); rdev->errmsg = get_pool_memory(PM_EMSG); *rdev->errmsg = 0; rdev->max_block_size = dcr->dev->max_block_size; @@ -213,6 +222,7 @@ static bool despool_data(DCR *dcr) rdcr->spool_fd = dcr->spool_fd; rdcr->jcr = jcr; /* set a valid jcr */ block = rdcr->block; + Dmsg1(800, "read/write block size = %d\n", block->buf_len); lseek(rdcr->spool_fd, 0, SEEK_SET); /* rewind */ @@ -253,9 +263,10 @@ static bool despool_data(DCR *dcr) V(dcr->dev->spool_mutex); free_memory(rdev->dev_name); free_pool_memory(rdev->errmsg); - free(rdev); + /* Be careful to NULL the jcr and free rdev after free_dcr() */ rdcr->jcr = NULL; free_dcr(rdcr); + free(rdev); unlock_device(dcr->dev); dcr->dev_locked = false; dcr->spooling = true; /* turn on spooling again */ @@ -320,10 +331,7 @@ static int read_block_from_spool_file(DCR *dcr, DEV_BLOCK *block) */ bool write_block_to_spool_file(DCR *dcr, DEV_BLOCK *block) { - ssize_t stat = 0; uint32_t wlen, hlen; /* length to write */ - int retry = 0; - spool_hdr hdr; bool despool = false; ASSERT(block->binbuf == ((uint32_t) (block->bufp - block->buf))); @@ -331,7 +339,7 @@ bool write_block_to_spool_file(DCR *dcr, DEV_BLOCK *block) return true; } - hlen = sizeof(hdr); + hlen = sizeof(spool_hdr); wlen = block->binbuf; P(dcr->dev->spool_mutex); dcr->spool_size += hlen + wlen; @@ -348,9 +356,8 @@ bool write_block_to_spool_file(DCR *dcr, DEV_BLOCK *block) } V(mutex); if (despool) { - char ec1[30]; #ifdef xDEBUG - char ec2[30], ec3[30], ec4[30]; + 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), @@ -358,9 +365,8 @@ bool write_block_to_spool_file(DCR *dcr, DEV_BLOCK *block) 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. Despooling %s bytes ...\n"), - edit_uint64_with_commas(dcr->dev->spool_size, ec1)); - if (!despool_data(dcr)) { + Jmsg(dcr->jcr, M_INFO, 0, _("User specified spool size reached.\n")); + if (!despool_data(dcr, false)) { Dmsg0(000, "Bad return from despool in write_block.\n"); return false; } @@ -372,54 +378,86 @@ bool write_block_to_spool_file(DCR *dcr, DEV_BLOCK *block) Jmsg(dcr->jcr, M_INFO, 0, _("Spooling data again ...\n")); } + + if (!write_spool_header(dcr, block)) { + return false; + } + if (!write_spool_data(dcr, block)) { + return false; + } + + Dmsg2(100, "Wrote block FI=%d LI=%d\n", block->FirstIndex, block->LastIndex); + empty_block(block); + return true; +} + +static bool write_spool_header(DCR *dcr, DEV_BLOCK *block) +{ + spool_hdr hdr; + ssize_t stat; + hdr.FirstIndex = block->FirstIndex; hdr.LastIndex = block->LastIndex; hdr.len = block->binbuf; /* Write header */ - for ( ;; ) { - stat = write(dcr->spool_fd, (char*)&hdr, (size_t)hlen); + for (int retry=0; retry<=1; retry++) { + stat = write(dcr->spool_fd, (char*)&hdr, sizeof(hdr)); if (stat == -1) { Jmsg(dcr->jcr, M_INFO, 0, _("Error writing header to spool file. ERR=%s\n"), strerror(errno)); } - if (stat != (ssize_t)hlen) { - if (!despool_data(dcr)) { - Jmsg(dcr->jcr, M_FATAL, 0, _("Fatal despooling error.")); - return false; + if (stat != (ssize_t)sizeof(hdr)) { + /* If we wrote something, truncate it, then despool */ + if (stat != -1) { + ftruncate(dcr->spool_fd, lseek(dcr->spool_fd, (off_t)0, SEEK_CUR) - stat); } - if (retry++ > 1) { + if (!despool_data(dcr, false)) { + Jmsg(dcr->jcr, M_FATAL, 0, _("Fatal despooling error.")); return false; } - continue; + continue; /* try again */ } - break; + return true; } + Jmsg(dcr->jcr, M_FATAL, 0, _("Retrying after header spooling error failed.\n")); + return false; +} + +static bool write_spool_data(DCR *dcr, DEV_BLOCK *block) +{ + ssize_t stat; /* Write data */ - for ( ;; ) { - stat = write(dcr->spool_fd, block->buf, (size_t)wlen); + for (int retry=0; retry<=1; retry++) { + stat = write(dcr->spool_fd, block->buf, (size_t)block->binbuf); if (stat == -1) { Jmsg(dcr->jcr, M_INFO, 0, _("Error writing data to spool file. ERR=%s\n"), strerror(errno)); } - if (stat != (ssize_t)wlen) { - if (!despool_data(dcr)) { + if (stat != (ssize_t)block->binbuf) { + /* + * If we wrote something, truncate it and the header, then despool + */ + if (stat != -1) { + ftruncate(dcr->spool_fd, lseek(dcr->spool_fd, (off_t)0, SEEK_CUR) + - stat - sizeof(spool_hdr)); + } + if (!despool_data(dcr, false)) { Jmsg(dcr->jcr, M_FATAL, 0, _("Fatal despooling error.")); return false; } - if (retry++ > 1) { + if (!write_spool_header(dcr, block)) { return false; } - continue; + continue; /* try again */ } - break; + return true; } - Dmsg2(100, "Wrote block FI=%d LI=%d\n", block->FirstIndex, block->LastIndex); - - empty_block(block); - return true; + Jmsg(dcr->jcr, M_FATAL, 0, _("Retrying after data spooling error failed.\n")); + return false; } + bool are_attributes_spooled(JCR *jcr) { return jcr->spool_attributes && jcr->dir_bsock->spool_fd;