From: Kern Sibbald Date: Sat, 13 Mar 2004 08:03:03 +0000 (+0000) Subject: Implement selecting another Volume if busy + cleanup spool messages X-Git-Tag: Release-1.34.0~55 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=bb659940f5398c4c4323d610cb06961c3ccc57a5;p=bacula%2Fbacula Implement selecting another Volume if busy + cleanup spool messages git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@1129 91ce42f0-d328-0410-95d8-f526ca767f89 --- diff --git a/bacula/src/cats/sql_find.c b/bacula/src/cats/sql_find.c index 925b063edc..6ba773dbe0 100644 --- a/bacula/src/cats/sql_find.c +++ b/bacula/src/cats/sql_find.c @@ -250,8 +250,8 @@ db_find_next_volume(JCR *jcr, B_DB *mdb, int item, bool InChanger, MEDIA_DBR *mr "FirstWritten,LastWritten,VolStatus,InChanger " "FROM Media WHERE PoolId=%u AND MediaType='%s' AND VolStatus='%s' " "%s " - "%s LIMIT 1", - mr->PoolId, mr->MediaType, mr->VolStatus, changer, order); + "%s LIMIT %d", + mr->PoolId, mr->MediaType, mr->VolStatus, changer, order, item); } if (!QUERY_DB(jcr, mdb, mdb->cmd)) { db_unlock(mdb); diff --git a/bacula/src/console/conio.c b/bacula/src/console/conio.c index fee692718e..7447ead95e 100755 --- a/bacula/src/console/conio.c +++ b/bacula/src/console/conio.c @@ -834,11 +834,13 @@ static void rawmode(FILE *input) if (!termtype) { printf("Cannot get terminal type.\n"); - exit(1); + normode(); + _exit(1); } if (tgetent(term_buffer, termtype) < 0) { printf("Cannot get terminal termcap entry.\n"); - exit(1); + normode(); + _exit(1); } t_width = t_height = -1; t_width = tgetnum("co") - 1; @@ -989,7 +991,8 @@ static void sigintcatcher(int sig) { brkflg++; if (brkflg > 1) { - exit(1); + normode(); + _exit(1); } signal(SIGINT, sigintcatcher); } diff --git a/bacula/src/dird/scheduler.c b/bacula/src/dird/scheduler.c index 1595999efa..bb9008b01e 100644 --- a/bacula/src/dird/scheduler.c +++ b/bacula/src/dird/scheduler.c @@ -32,7 +32,7 @@ #include "bacula.h" #include "dird.h" -/* #define PHIL */ +/* #define SCHED_DEBUG */ /* Local variables */ @@ -315,7 +315,7 @@ static void add_job(JOB *job, RUN *run, time_t now, time_t runtime) * do run any job scheduled less than a minute ago. */ if (((runtime - run->last_run) < 61) || ((runtime+59) < now)) { -#ifdef PHIL +#ifdef SCHED_DEBUG char dt[50], dt1[50], dt2[50]; bstrftime_nc(dt, sizeof(dt), runtime); bstrftime_nc(dt1, sizeof(dt1), run->last_run); @@ -352,15 +352,17 @@ static void add_job(JOB *job, RUN *run, time_t now, time_t runtime) jobs_to_run->append(je); dump_job(je, "Appended job"); } +#ifdef SCHED_DEBUG foreach_dlist(ji, jobs_to_run) { dump_job(ji, "Run queue"); } Dmsg0(000, "End run queue\n"); +#endif } static void dump_job(job_item *ji, char *msg) { -#ifdef PHIL +#ifdef SCHED_DEBUG char dt[MAX_TIME_LENGTH]; int save_debug = debug_level; debug_level = 200; diff --git a/bacula/src/lib/bnet.c b/bacula/src/lib/bnet.c index a95d1e5cb4..0cc4ccbd47 100644 --- a/bacula/src/lib/bnet.c +++ b/bacula/src/lib/bnet.c @@ -92,7 +92,7 @@ static int32_t write_nbytes(BSOCK *bsock, char *ptr, int32_t nbytes) if (bsock->spool) { nwritten = fwrite(ptr, 1, nbytes, bsock->spool_fd); if (nwritten != nbytes) { - Jmsg1(bsock->jcr, M_ERROR, 0, _("Spool write error. ERR=%s\n"), strerror(errno)); + Jmsg1(bsock->jcr, M_FATAL, 0, _("Attr spool write error. ERR=%s\n"), strerror(errno)); Dmsg2(400, "nwritten=%d nbytes=%d.\n", nwritten, nbytes); return -1; } @@ -296,14 +296,14 @@ int bnet_despool_to_bsock(BSOCK *bsock) nbytes = fread(bsock->msg, 1, bsock->msglen, bsock->spool_fd); if (nbytes != (size_t)bsock->msglen) { Dmsg2(400, "nbytes=%d msglen=%d\n", nbytes, bsock->msglen); - Jmsg1(bsock->jcr, M_ERROR, 0, _("fread error. ERR=%s\n"), strerror(errno)); + Jmsg1(bsock->jcr, M_FATAL, 0, _("fread attr spool error. ERR=%s\n"), strerror(errno)); return 0; } } bnet_send(bsock); } if (ferror(bsock->spool_fd)) { - Jmsg1(bsock->jcr, M_ERROR, 0, _("fread error. ERR=%s\n"), strerror(errno)); + Jmsg1(bsock->jcr, M_FATAL, 0, _("fread attr spool error. ERR=%s\n"), strerror(errno)); return 0; } return 1; diff --git a/bacula/src/lib/message.c b/bacula/src/lib/message.c index c8f9aac557..a5d49d1bd6 100755 --- a/bacula/src/lib/message.c +++ b/bacula/src/lib/message.c @@ -555,6 +555,7 @@ void dispatch_message(JCR *jcr, int type, int level, char *msg) if (type == M_ABORT || type == M_ERROR_TERM) { fputs(msg, stdout); /* print this here to INSURE that it is printed */ + fflush(stdout); #if defined(HAVE_CYGWIN) || defined(HAVE_WIN32) MessageBox(NULL, msg, "Bacula", MB_OK); #endif @@ -1118,11 +1119,11 @@ again: pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2); goto again; } - P(msg_queue_mutex); item = (MQUEUE_ITEM *)malloc(sizeof(MQUEUE_ITEM) + strlen(pool_buf) + 1); item->type = type; item->level = level; strcpy(item->msg, pool_buf); + P(msg_queue_mutex); jcr->msg_queue->append(item); V(msg_queue_mutex); free_memory(pool_buf); diff --git a/bacula/src/stored/append.c b/bacula/src/stored/append.c index 9375fd8f7c..cffb98a4ad 100644 --- a/bacula/src/stored/append.c +++ b/bacula/src/stored/append.c @@ -185,7 +185,7 @@ int do_append_data(JCR *jcr) if (!write_block_to_device(jcr->dcr, block)) { Dmsg2(90, "Got write_block_to_dev error on device %s. %s\n", dev_name(dev), strerror_dev(dev)); - Jmsg(jcr, M_FATAL, 0, _("Cannot fixup device error. %s\n"), + Jmsg(jcr, M_FATAL, 0, _("Fatal device error: ERR=%s\n"), strerror_dev(dev)); ok = false; break; diff --git a/bacula/src/stored/askdir.c b/bacula/src/stored/askdir.c index ca692e7636..d8ae98f0cd 100644 --- a/bacula/src/stored/askdir.c +++ b/bacula/src/stored/askdir.c @@ -149,10 +149,44 @@ int dir_get_volume_info(JCR *jcr, enum get_vol_info_rw writing) int dir_find_next_appendable_volume(JCR *jcr) { BSOCK *dir = jcr->dir_bsock; + JCR *njcr; Dmsg0(200, "dir_find_next_appendable_volume\n"); - bnet_fsend(dir, Find_media, jcr->Job, 1); - return do_get_volume_info(jcr); + for (int vol_index=1; vol_index < 3; vol_index++) { + bnet_fsend(dir, Find_media, jcr->Job, vol_index); + if (do_get_volume_info(jcr)) { + Dmsg1(200, "Got possible Vol=%s\n", jcr->VolumeName); + bool found = false; + /* + * Walk through all jobs and see if the volume is + * already mounted. If so, try a different one. + * This would be better done by walking through + * all the devices. + */ + lock_jcr_chain(); + foreach_jcr(njcr) { + if (jcr == njcr) { + continue; /* us */ + } + if (strcmp(jcr->VolumeName, njcr->VolumeName) == 0) { + found = true; + Dmsg1(200, "Vol in use by JobId=%u\n", njcr->JobId); + free_locked_jcr(njcr); + break; + } + free_locked_jcr(njcr); + } + unlock_jcr_chain(); + if (!found) { + Dmsg0(200, "dir_find_next_appendable_volume return true\n"); + return true; /* Got good Volume */ + } + } else { + break; + } + } + Dmsg0(200, "dir_find_next_appendable_volume return false\n"); + return false; } diff --git a/bacula/src/stored/protos.h b/bacula/src/stored/protos.h index 4fd66f71f5..a81ccb3cd2 100644 --- a/bacula/src/stored/protos.h +++ b/bacula/src/stored/protos.h @@ -210,3 +210,5 @@ bool commit_attribute_spool (JCR *jcr); bool write_block_to_spool_file (DCR *dcr, DEV_BLOCK *block); bool open_spool_file (JCR *jcr, BSOCK *bs); bool close_spool_file (JCR *jcr, BSOCK *bs); +void list_spool_stats (BSOCK *bs); + diff --git a/bacula/src/stored/spool.c b/bacula/src/stored/spool.c index 367d897a25..6647df43a7 100644 --- a/bacula/src/stored/spool.c +++ b/bacula/src/stored/spool.c @@ -30,15 +30,31 @@ /* Forward referenced subroutines */ static void make_unique_data_spool_filename(JCR *jcr, POOLMEM **name); -static int open_data_spool_file(JCR *jcr); -static int close_data_spool_file(JCR *jcr); +static bool open_data_spool_file(JCR *jcr); +static bool close_data_spool_file(JCR *jcr); static bool despool_data(DCR *dcr); -static int read_block_from_spool_file(DCR *dcr, DEV_BLOCK *block); +static int read_block_from_spool_file(DCR *dcr, DEV_BLOCK *block); + +struct spool_stats_t { + 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_attr_jobs; + uint64_t max_data_size; /* max data size */ + uint64_t max_attr_size; + uint64_t data_size; /* current data size (all jobs running) */ + uint64_t attr_size; +}; + +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +spool_stats_t spool_stats; +/* + * Header for data spool record */ struct spool_hdr { - int32_t FirstIndex; - int32_t LastIndex; - uint32_t len; + int32_t FirstIndex; /* FirstIndex for buffer */ + int32_t LastIndex; /* LastIndex for buffer */ + uint32_t len; /* length of next buffer */ }; enum { @@ -47,6 +63,17 @@ enum { RB_OK }; +void list_spool_stats(BSOCK *bs) +{ + char ed1[30], ed2[30]; + bnet_fsend(bs, "Data spooling: %d active jobs %s bytes; %d 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)); + bnet_fsend(bs, "Attr spooling: %d active jobs; %d total jobs %s max bytes/job.\n", + spool_stats.attr_jobs, + spool_stats.total_attr_jobs, edit_uint64_with_commas(spool_stats.max_attr_size, ed2)); +} + bool begin_data_spool(JCR *jcr) { bool stat = true; @@ -56,6 +83,10 @@ bool begin_data_spool(JCR *jcr) stat = open_data_spool_file(jcr); if (stat) { jcr->dcr->spooling = true; + Jmsg(jcr, M_INFO, 0, _("Spooling data ...\n")); + P(mutex); + spool_stats.data_jobs++; + V(mutex); } } return stat; @@ -98,7 +129,7 @@ static void make_unique_data_spool_filename(JCR *jcr, POOLMEM **name) } -static int open_data_spool_file(JCR *jcr) +static bool open_data_spool_file(JCR *jcr) { POOLMEM *name = get_pool_memory(PM_MESSAGE); int spool_fd; @@ -108,19 +139,25 @@ static int open_data_spool_file(JCR *jcr) jcr->dcr->spool_fd = spool_fd; jcr->spool_attributes = true; } else { - Jmsg(jcr, M_ERROR, 0, "open data spool file %s failed: ERR=%s\n", name, strerror(errno)); + Jmsg(jcr, M_ERROR, 0, _("Open data spool file %s failed: ERR=%s\n"), name, strerror(errno)); free_pool_memory(name); - return 0; + return false; } Dmsg1(100, "Created spool file: %s\n", name); free_pool_memory(name); - return 1; + return true; } -static int close_data_spool_file(JCR *jcr) +static bool close_data_spool_file(JCR *jcr) { POOLMEM *name = get_pool_memory(PM_MESSAGE); + P(mutex); + spool_stats.data_jobs--; + spool_stats.total_data_jobs++; + spool_stats.data_size -= jcr->dcr->spool_size; + V(mutex); + make_unique_data_spool_filename(jcr, &name); close(jcr->dcr->spool_fd); jcr->dcr->spool_fd = -1; @@ -128,7 +165,7 @@ static int close_data_spool_file(JCR *jcr) unlink(name); Dmsg1(100, "Deleted spool file: %s\n", name); free_pool_memory(name); - return 1; + return true; } static bool despool_data(DCR *dcr) @@ -176,15 +213,19 @@ static bool despool_data(DCR *dcr) lseek(rdcr->spool_fd, 0, SEEK_SET); /* rewind */ if (ftruncate(rdcr->spool_fd, 0) != 0) { + Jmsg(dcr->jcr, M_FATAL, 0, _("Ftruncate spool file error. ERR=%s\n"), + strerror(errno)); Dmsg1(000, "Bad return from ftruncate. ERR=%s\n", strerror(errno)); ok = false; } + P(mutex); + spool_stats.data_size -= dcr->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 */ V(dcr->dev->spool_mutex); - free_memory(rdev->dev_name); free_pool_memory(rdev->errmsg); free(rdev); @@ -216,23 +257,23 @@ static int read_block_from_spool_file(DCR *dcr, DEV_BLOCK *block) return RB_EOT; } else if (stat != (ssize_t)rlen) { if (stat == -1) { - Jmsg(dcr->jcr, M_FATAL, 0, "Spool read error. ERR=%s\n", strerror(errno)); + Jmsg(dcr->jcr, M_FATAL, 0, _("Spool header read error. ERR=%s\n"), strerror(errno)); } else { Dmsg2(000, "Spool read error. Wanted %u bytes, got %u\n", rlen, stat); - Jmsg2(dcr->jcr, M_FATAL, 0, "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); } return RB_ERROR; } rlen = hdr.len; if (rlen > block->buf_len) { Dmsg2(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); + 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) { - Dmsg2(000, "Spool read error. Wanted %u bytes, got %u\n", rlen, stat); - Jmsg2(dcr->jcr, M_FATAL, 0, "Spool read error. Wanted %u bytes, got %u\n", rlen, stat); + Dmsg2(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); return RB_ERROR; } /* Setup write pointers */ @@ -262,7 +303,6 @@ bool write_block_to_spool_file(DCR *dcr, DEV_BLOCK *block) ASSERT(block->binbuf == ((uint32_t) (block->bufp - block->buf))); if (block->binbuf <= WRITE_BLKHDR_LENGTH) { /* Does block have data in it? */ - Dmsg0(100, "return write_block_to_dev no data to write\n"); return true; } @@ -276,6 +316,12 @@ bool write_block_to_spool_file(DCR *dcr, DEV_BLOCK *block) despool = true; } V(dcr->dev->spool_mutex); + P(mutex); + spool_stats.data_size += hlen + wlen; + if (spool_stats.data_size > spool_stats.max_data_size) { + spool_stats.max_data_size = spool_stats.data_size; + } + V(mutex); if (despool) { char ec1[30], ec2[30], ec3[30], ec4[30]; Dmsg4(100, "Despool in write_block_to_spool_file max_size=%s size=%s " @@ -284,15 +330,17 @@ bool write_block_to_spool_file(DCR *dcr, DEV_BLOCK *block) 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)); - despool = false; + Jmsg(dcr->jcr, M_INFO, 0, _("User specified spool size reached. Despooling ...\n")); if (!despool_data(dcr)) { Dmsg0(000, "Bad return from despool in write_block.\n"); return false; } + /* Despooling cleard these variables so reset them */ P(dcr->dev->spool_mutex); dcr->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")); } hdr.FirstIndex = block->FirstIndex; @@ -302,8 +350,12 @@ bool write_block_to_spool_file(DCR *dcr, DEV_BLOCK *block) /* Write header */ for ( ;; ) { stat = write(dcr->spool_fd, (char*)&hdr, (size_t)hlen); + 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 (retry++ > 1) { @@ -317,8 +369,12 @@ bool write_block_to_spool_file(DCR *dcr, DEV_BLOCK *block) /* Write data */ for ( ;; ) { stat = write(dcr->spool_fd, block->buf, (size_t)wlen); + 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)) { + Jmsg(dcr->jcr, M_FATAL, 0, _("Fatal despooling error.")); return false; } if (retry++ > 1) { @@ -374,7 +430,7 @@ bool commit_attribute_spool(JCR *jcr) static void make_unique_spool_filename(JCR *jcr, POOLMEM **name, int fd) { - Mmsg(name, "%s/%s.spool.%s.%d", working_directory, my_name, + Mmsg(name, "%s/%s.attr.spool.%s.%d", working_directory, my_name, jcr->Job, fd); } @@ -385,10 +441,13 @@ bool open_spool_file(JCR *jcr, BSOCK *bs) make_unique_spool_filename(jcr, &name, bs->fd); bs->spool_fd = fopen(mp_chr(name), "w+"); if (!bs->spool_fd) { - Jmsg(jcr, M_ERROR, 0, "fopen spool file %s failed: ERR=%s\n", name, strerror(errno)); + Jmsg(jcr, M_ERROR, 0, _("fopen attr spool file %s failed: ERR=%s\n"), name, strerror(errno)); free_pool_memory(name); return false; } + P(mutex); + spool_stats.attr_jobs++; + V(mutex); free_pool_memory(name); return true; } @@ -396,7 +455,19 @@ bool open_spool_file(JCR *jcr, BSOCK *bs) bool close_spool_file(JCR *jcr, BSOCK *bs) { POOLMEM *name = get_pool_memory(PM_MESSAGE); - + ssize_t size; + + fseek(bs->spool_fd, 0, SEEK_END); + size = ftell(bs->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; + } + } + spool_stats.attr_jobs--; + spool_stats.total_attr_jobs++; + V(mutex); make_unique_spool_filename(jcr, &name, bs->fd); fclose(bs->spool_fd); unlink(mp_chr(name)); diff --git a/bacula/src/stored/status.c b/bacula/src/stored/status.c index 45a5dd7f10..18b08018fd 100644 --- a/bacula/src/stored/status.c +++ b/bacula/src/stored/status.c @@ -172,6 +172,8 @@ int status_cmd(JCR *jcr) #endif bnet_fsend(user, "====\n"); + list_spool_stats(user); + bnet_sig(user, BNET_EOD); return 1; }