From: <ke...@us...> - 2008-03-19 16:31:32
|
Revision: 6632 http://bacula.svn.sourceforge.net/bacula/?rev=6632&view=rev Author: kerns Date: 2008-03-19 09:31:36 -0700 (Wed, 19 Mar 2008) Log Message: ----------- Move Added Paths: ----------- branches/Branch-2.2/bacula/patches/2.0.x/2.2.7-fpformat.patch branches/Branch-2.2/bacula/patches/2.0.x/2.2.7-jobdefs-migtype.patch branches/Branch-2.2/bacula/patches/2.0.x/2.2.7-mysql-batch-timeout.patch branches/Branch-2.2/bacula/patches/2.0.x/2.2.7-old-postgresql.patch branches/Branch-2.2/bacula/patches/2.0.x/2.2.7-reserve.patch branches/Branch-2.2/bacula/patches/2.2.8-deadlock.patch Removed Paths: ------------- branches/Branch-2.2/bacula/patches/2.2.7-fpformat.patch branches/Branch-2.2/bacula/patches/2.2.7-jobdefs-migtype.patch branches/Branch-2.2/bacula/patches/2.2.7-mysql-batch-timeout.patch branches/Branch-2.2/bacula/patches/2.2.7-old-postgresql.patch branches/Branch-2.2/bacula/patches/2.2.7-reserve.patch Copied: branches/Branch-2.2/bacula/patches/2.0.x/2.2.7-fpformat.patch (from rev 6531, branches/Branch-2.2/bacula/patches/2.2.7-fpformat.patch) =================================================================== --- branches/Branch-2.2/bacula/patches/2.0.x/2.2.7-fpformat.patch (rev 0) +++ branches/Branch-2.2/bacula/patches/2.0.x/2.2.7-fpformat.patch 2008-03-19 16:31:36 UTC (rev 6632) @@ -0,0 +1,120 @@ + + This patch fixes a float point editing bug introduced in 2.2.7 (I think) + causing the rate fields to be formated incorrectly (actually trunctated). + This fixes bug #1036. + + Apply it to version 2.2.7 with: + + cd <bacula-source> + patch -p0 <2.2.7-fpformat.patch + ./configure <your-options> + make + ... + make install + + +Index: src/lib/bsnprintf.c +=================================================================== +--- src/lib/bsnprintf.c (revision 6183) ++++ src/lib/bsnprintf.c (working copy) +@@ -16,7 +16,7 @@ + /* + Bacula® - The Network Backup Solution + +- Copyright (C) 2005-2007 Free Software Foundation Europe e.V. ++ Copyright (C) 2005-2008 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. +@@ -566,11 +566,11 @@ + return result; + } + +-static long round(LDOUBLE value) ++static int64_t round(LDOUBLE value) + { +- long intpart; ++ int64_t intpart; + +- intpart = (long)value; ++ intpart = (int64_t)value; + value = value - intpart; + if (value >= 0.5) + intpart++; +@@ -584,8 +584,8 @@ + int signvalue = 0; + LDOUBLE ufvalue; + #ifndef HAVE_FCVT +- char iconvert[25]; +- char fconvert[25]; ++ char iconvert[311]; ++ char fconvert[311]; + #else + char iconvert[311]; + char fconvert[311]; +@@ -602,6 +602,7 @@ + int caps = 0; + int64_t intpart; + int64_t fracpart; ++ const char *cvt_str; + + /* + * AIX manpage says the default is 0, but Solaris says the default +@@ -625,7 +626,7 @@ + #endif + + #ifndef HAVE_FCVT +- intpart = (long)ufvalue; ++ intpart = (int64_t)ufvalue; + + /* + * Sorry, we only support 9 digits past the decimal because of our +@@ -645,28 +646,30 @@ + } + + #ifdef DEBUG_SNPRINTF +- printf("fmtfp: %g %d.%d min=%d max=%d\n", ++ printf("fmtfp: %g %lld.%lld min=%d max=%d\n", + (double)fvalue, intpart, fracpart, min, max); + #endif + + /* Convert integer part */ ++ cvt_str = caps ? "0123456789ABCDEF" : "0123456789abcdef"; + do { +- iconvert[iplace++] = +- (caps ? "0123456789ABCDEF" : "0123456789abcdef")[intpart % 10]; ++ iconvert[iplace++] = cvt_str[(int)(intpart % 10)]; + intpart = (intpart / 10); +- } while (intpart && (iplace < (int)sizeof(iplace))); +- if (iplace == (int)sizeof(iplace)) { ++ } while (intpart && (iplace < (int)sizeof(iconvert))); ++ ++ if (iplace == (int)sizeof(fconvert)) { + iplace--; + } + iconvert[iplace] = 0; + + /* Convert fractional part */ ++ cvt_str = caps ? "0123456789ABCDEF" : "0123456789abcdef"; + do { +- fconvert[fplace++] = +- (caps ? "0123456789ABCDEF" : "0123456789abcdef")[fracpart % 10]; ++ fconvert[fplace++] = cvt_str[fracpart % 10]; + fracpart = (fracpart / 10); +- } while (fracpart && (fplace < (int)sizeof(fplace))); +- if (fplace == (int)sizeof(fplace)) { ++ } while (fracpart && (fplace < (int)sizeof(fconvert))); ++ ++ if (fplace == (int)sizeof(fconvert)) { + fplace--; + } + fconvert[fplace] = 0; +@@ -825,7 +828,7 @@ + NULL + }; + double fp_nums[] = { -1.5, 134.21, 91340.2, 341.1234, 0203.9, 0.96, 0.996, +- 0.9996, 1.996, 4.136, 6442452944.1234, 0 ++ 0.9996, 1.996, 4.136, 6442452944.1234, 0, 23365.5 + }; + #endif + char *int_fmt[] = { Copied: branches/Branch-2.2/bacula/patches/2.0.x/2.2.7-jobdefs-migtype.patch (from rev 6531, branches/Branch-2.2/bacula/patches/2.2.7-jobdefs-migtype.patch) =================================================================== --- branches/Branch-2.2/bacula/patches/2.0.x/2.2.7-jobdefs-migtype.patch (rev 0) +++ branches/Branch-2.2/bacula/patches/2.0.x/2.2.7-jobdefs-migtype.patch 2008-03-19 16:31:36 UTC (rev 6632) @@ -0,0 +1,56 @@ + + This patch permits to use migration options with JobDefs. + This patch fixes bug #1028. + + Apply the patch to 2.2.7 (and possibly any 2.2.x version with): + + cd <bacula-source> + patch -p0 <2.2.7-jobdefs-migtype.patch + ./configure <your-options> + make + ... + make install + +Index: src/dird/dird.c +=================================================================== +--- src/dird/dird.c (revision 6183) ++++ src/dird/dird.c (working copy) +@@ -58,6 +58,7 @@ + void store_jobtype(LEX *lc, RES_ITEM *item, int index, int pass); + void store_level(LEX *lc, RES_ITEM *item, int index, int pass); + void store_replace(LEX *lc, RES_ITEM *item, int index, int pass); ++void store_migtype(LEX *lc, RES_ITEM *item, int index, int pass); + void init_device_resources(); + + static char *runjob = NULL; +@@ -698,6 +699,7 @@ + job_items[i].handler == store_jobtype || + job_items[i].handler == store_level || + job_items[i].handler == store_pint || ++ job_items[i].handler == store_migtype || + job_items[i].handler == store_replace) { + def_ivalue = (int *)((char *)(job->jobdefs) + offset); + Dmsg5(400, "Job \"%s\", field \"%s\" def_ivalue=%d item %d offset=%u\n", +Index: src/dird/dird_conf.c +=================================================================== +--- src/dird/dird_conf.c (revision 6183) ++++ src/dird/dird_conf.c (working copy) +@@ -74,8 +74,8 @@ + void store_level(LEX *lc, RES_ITEM *item, int index, int pass); + void store_replace(LEX *lc, RES_ITEM *item, int index, int pass); + void store_acl(LEX *lc, RES_ITEM *item, int index, int pass); ++void store_migtype(LEX *lc, RES_ITEM *item, int index, int pass); + static void store_device(LEX *lc, RES_ITEM *item, int index, int pass); +-static void store_migtype(LEX *lc, RES_ITEM *item, int index, int pass); + static void store_runscript(LEX *lc, RES_ITEM *item, int index, int pass); + static void store_runscript_when(LEX *lc, RES_ITEM *item, int index, int pass); + static void store_runscript_cmd(LEX *lc, RES_ITEM *item, int index, int pass); +@@ -1548,7 +1548,7 @@ + * Store JobType (backup, verify, restore) + * + */ +-static void store_migtype(LEX *lc, RES_ITEM *item, int index, int pass) ++void store_migtype(LEX *lc, RES_ITEM *item, int index, int pass) + { + int token, i; + Copied: branches/Branch-2.2/bacula/patches/2.0.x/2.2.7-mysql-batch-timeout.patch (from rev 6531, branches/Branch-2.2/bacula/patches/2.2.7-mysql-batch-timeout.patch) =================================================================== --- branches/Branch-2.2/bacula/patches/2.0.x/2.2.7-mysql-batch-timeout.patch (rev 0) +++ branches/Branch-2.2/bacula/patches/2.0.x/2.2.7-mysql-batch-timeout.patch 2008-03-19 16:31:36 UTC (rev 6632) @@ -0,0 +1,30 @@ + + This patch fixes bug #1034 about Temporary MySQL table 'batch' + disappears if MySQL connection times out. + + Apply the patch to 2.2.7 (and possibly any 2.2.x version with): + + cd <bacula-source> + patch -p0 <2.2.7-mysql-batch-timeout.patch + ./configure <your-options> + make + ... + make install + + + +Index: src/cats/mysql.c +=================================================================== +--- src/cats/mysql.c (r\xE9vision 6192) ++++ src/cats/mysql.c (copie de travail) +@@ -205,6 +205,10 @@ + Dmsg3(100, "opendb ref=%d connected=%d db=%p\n", mdb->ref_count, + mdb->connected, mdb->db); + ++ /* Set connection timeout to 8 days specialy for batch mode */ ++ sql_query(mdb, "SET wait_timeout=691200"); ++ sql_query(mdb, "SET interactive_timeout=691200"); ++ + V(mutex); + return 1; + } Copied: branches/Branch-2.2/bacula/patches/2.0.x/2.2.7-old-postgresql.patch (from rev 6531, branches/Branch-2.2/bacula/patches/2.2.7-old-postgresql.patch) =================================================================== --- branches/Branch-2.2/bacula/patches/2.0.x/2.2.7-old-postgresql.patch (rev 0) +++ branches/Branch-2.2/bacula/patches/2.0.x/2.2.7-old-postgresql.patch 2008-03-19 16:31:36 UTC (rev 6632) @@ -0,0 +1,26 @@ + + If you have an old version of PostgreSQL, for example, + version 7.3 or older, it may not properly build with the current + Bacula release due to incompatible changes in the PostgreSQL + header files between version. Only in the case that build fails, + you might try applying this patch with: + + cd <bacula-2.2.7-source> + patch -p1 <2.2.7-old-postgresql.patch + ./configure <your-options> + make + ... + make install + + +diff -uNr bacula-2.2.7/src/cats/postgresql.c bacula-2.2.7-fixed/src/cats/postgresql.c +--- bacula-2.2.7/src/cats/postgresql.c 2007-12-08 04:54:55.000000000 -0500 ++++ bacula-2.2.7-fixed/src/cats/postgresql.c 2007-12-29 08:34:10.000000000 -0500 +@@ -47,7 +47,6 @@ + #ifdef HAVE_POSTGRESQL + + #include "postgres_ext.h" /* needed for NAMEDATALEN */ +-#include "pg_config_manual.h" /* get NAMEDATALEN on version 8.3 or later */ + + /* ----------------------------------------------------------------------- + * Copied: branches/Branch-2.2/bacula/patches/2.0.x/2.2.7-reserve.patch (from rev 6531, branches/Branch-2.2/bacula/patches/2.2.7-reserve.patch) =================================================================== --- branches/Branch-2.2/bacula/patches/2.0.x/2.2.7-reserve.patch (rev 0) +++ branches/Branch-2.2/bacula/patches/2.0.x/2.2.7-reserve.patch 2008-03-19 16:31:36 UTC (rev 6632) @@ -0,0 +1,1467 @@ + + This patch has a number of cleanups and improvements to the SD + reservations system. It should fix a number of problems with + dual drive autochangers as well ensure that volume use durations + and max volume jobs are better respected. + + Apply it to version 2.2.7 (possibly some earlier versions) with: + + cd <bacula-source> + patch -p1 <2.2.7-reserve.patch + ./configure <your options> + make + ... + make install + + +diff -ur k1/src/lib/message.c k3/src/lib/message.c +--- k1/src/lib/message.c 2007-10-19 13:47:58.000000000 +0200 ++++ k3/src/lib/message.c 2007-12-22 19:13:00.000000000 +0100 +@@ -54,6 +54,7 @@ + int verbose = 0; /* increase User messages */ + /* Keep debug level set to zero by default */ + int debug_level = 0; /* debug level */ ++bool dbg_timestamp = false; /* print timestamp in debug output */ + time_t daemon_start_time = 0; /* Daemon start time */ + const char *version = VERSION " (" BDATE ")"; + char my_name[30]; /* daemon name is stored here */ +diff -ur k1/src/lib/message.h k3/src/lib/message.h +--- k1/src/lib/message.h 2007-10-03 13:36:47.000000000 +0200 ++++ k3/src/lib/message.h 2007-12-22 19:13:06.000000000 +0100 +@@ -154,6 +154,7 @@ + extern DLL_IMP_EXP sql_escape p_sql_escape; + + extern DLL_IMP_EXP int debug_level; ++extern DLL_IMP_EXP bool dbg_timestamp; /* print timestamp in debug output */ + extern DLL_IMP_EXP int verbose; + extern DLL_IMP_EXP char my_name[]; + extern DLL_IMP_EXP const char * working_directory; +diff -ur k1/src/stored/acquire.c k3/src/stored/acquire.c +--- k1/src/stored/acquire.c 2007-09-14 11:49:06.000000000 +0200 ++++ k3/src/stored/acquire.c 2007-12-22 19:12:23.000000000 +0100 +@@ -30,7 +30,7 @@ + * + * Kern Sibbald, August MMII + * +- * Version $Id: acquire.c 5552 2007-09-14 09:49:06Z kerns $ ++ * Version $Id: acquire.c 6081 2007-12-21 14:11:40Z kerns $ + */ + + #include "bacula.h" /* pull in global headers */ +@@ -38,6 +38,7 @@ + + /* Forward referenced functions */ + static void attach_dcr_to_dev(DCR *dcr); ++static bool is_suitable_volume_mounted(DCR *dcr); + + + /********************************************************************* +@@ -316,9 +317,9 @@ + */ + DCR *acquire_device_for_append(DCR *dcr) + { +- bool release = false; +- bool recycle = false; + bool do_mount = false; ++ bool release = false; ++ bool have_vol; + DEVICE *dev = dcr->dev; + JCR *jcr = dcr->jcr; + +@@ -337,6 +338,11 @@ + goto get_out; + } + ++ /* ++ * have_vol defines whether or not mount_next_write_volume should ++ * ask the Director again about what Volume to use. ++ */ ++ have_vol = is_suitable_volume_mounted(dcr); + if (dev->can_append()) { + Dmsg0(190, "device already in append.\n"); + /* +@@ -351,25 +357,11 @@ + * dcr->VolumeName is what we pass into the routines, or + * get back from the subroutines. + */ +- bstrncpy(dcr->VolumeName, dev->VolHdr.VolumeName, sizeof(dcr->VolumeName)); +- if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE) && ++ if (!have_vol && + !(dir_find_next_appendable_volume(dcr) && + strcmp(dev->VolHdr.VolumeName, dcr->VolumeName) == 0)) { /* wrong tape mounted */ +- Dmsg2(190, "Wrong tape mounted: %s. wants:%s\n", dev->VolHdr.VolumeName, +- dcr->VolumeName); +- /* Release volume reserved by dir_find_next_appendable_volume() */ +- if (dcr->VolumeName[0]) { +- volume_unused(dcr); +- } +- if (dev->num_writers != 0) { +- Jmsg3(jcr, M_FATAL, 0, _("Wanted to append to Volume \"%s\", but device %s is busy writing on \"%s\" .\n"), +- dcr->VolumeName, dev->print_name(), dev->VolHdr.VolumeName); +- Dmsg3(200, "Wanted to append to Volume \"%s\", but device %s is busy writing on \"%s\" .\n", +- dcr->VolumeName, dev->print_name(), dev->VolHdr.VolumeName); +- goto get_out; +- } + /* Wrong tape mounted, release it, then fall through to get correct one */ +- Dmsg0(190, "Wrong tape mounted, release and try mount.\n"); ++ Dmsg0(50, "Wrong tape mounted, release and try mount.\n"); + release = true; + do_mount = true; + } else { +@@ -378,14 +370,17 @@ + * we do not need to do mount_next_write_volume(), unless + * we need to recycle the tape. + */ +- recycle = strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") == 0; +- Dmsg1(190, "Correct tape mounted. recycle=%d\n", recycle); +- if (recycle && dev->num_writers != 0) { ++ do_mount = strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") == 0; ++ Dmsg2(190, "jid=%u Correct tape mounted. recycle=%d\n", ++ (uint32_t)jcr->JobId, do_mount); ++#ifdef xxx ++ if (do_mount && dev->num_writers != 0) { + Jmsg(jcr, M_FATAL, 0, _("Cannot recycle volume \"%s\"" + " on device %s because it is in use by another job.\n"), + dev->VolHdr.VolumeName, dev->print_name()); + goto get_out; + } ++#endif + if (dev->num_writers == 0) { + memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo)); + } +@@ -415,21 +410,23 @@ + } + } else { + /* Not already in append mode, so mount the device */ +- Dmsg0(190, "Not in append mode, try mount.\n"); ++ Dmsg2(190, "jid=%u Not in append mode, try mount have_vol=%d\n", ++ (uint32_t)jcr->JobId, have_vol); ++ + ASSERT(dev->num_writers == 0); + do_mount = true; + } + +- if (do_mount || recycle) { +- Dmsg0(190, "Do mount_next_write_vol\n"); +- bool mounted = mount_next_write_volume(dcr, release); ++ if (do_mount || !have_vol) { ++ Dmsg1(190, "jid=%u Do mount_next_write_vol\n", (uint32_t)jcr->JobId); ++ bool mounted = mount_next_write_volume(dcr, have_vol, release); + if (!mounted) { + if (!job_canceled(jcr)) { + /* Reduce "noise" -- don't print if job canceled */ + Jmsg(jcr, M_FATAL, 0, _("Could not ready device %s for append.\n"), + dev->print_name()); +- Dmsg1(200, "Could not ready device %s for append.\n", +- dev->print_name()); ++ Dmsg2(200, "jid=%u Could not ready device %s for append.\n", ++ (uint32_t)jcr->JobId, dev->print_name()); + } + goto get_out; + } +@@ -441,11 +438,12 @@ + jcr->NumWriteVolumes = 1; + } + dev->VolCatInfo.VolCatJobs++; /* increment number of jobs on vol */ +- dir_update_volume_info(dcr, false); /* send Volume info to Director */ ++ dir_update_volume_info(dcr, false, false); /* send Volume info to Director */ + dev->dlock(); + if (dcr->reserved_device) { + dev->reserved_device--; +- Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name()); ++ Dmsg3(100, "jid=%u Dec reserve=%d dev=%s\n", (uint32_t)jcr->JobId, ++ dev->reserved_device, dev->print_name()); + dcr->reserved_device = false; + } + dev->dunblock(DEV_LOCKED); +@@ -458,7 +456,8 @@ + dev->dlock(); + if (dcr->reserved_device) { + dev->reserved_device--; +- Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name()); ++ Dmsg3(100, "jid=%u Dec reserve=%d dev=%s\n", (uint32_t)jcr->JobId, ++ dev->reserved_device, dev->print_name()); + dcr->reserved_device = false; + } + dev->dunblock(DEV_LOCKED); +@@ -466,6 +465,18 @@ + } + + ++static bool is_suitable_volume_mounted(DCR *dcr) ++{ ++ DEVICE *dev = dcr->dev; ++ ++ /* Volume mounted? */ ++ if (dev->VolHdr.VolumeName[0] == 0) { ++ return false; /* no */ ++ } ++ bstrncpy(dcr->VolumeName, dev->VolHdr.VolumeName, sizeof(dcr->VolumeName)); ++ return dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE); ++} ++ + /* + * This job is done, so release the device. From a Unix standpoint, + * the device remains open. +@@ -496,7 +507,7 @@ + if (dev->can_read()) { + dev->clear_read(); /* clear read bit */ + Dmsg0(100, "dir_update_vol_info. Release0\n"); +- dir_update_volume_info(dcr, false); /* send Volume info to Director */ ++ dir_update_volume_info(dcr, false, false); /* send Volume info to Director */ + + } else if (dev->num_writers > 0) { + /* +@@ -522,7 +533,7 @@ + dev->VolCatInfo.VolCatFiles = dev->file; /* set number of files */ + /* Note! do volume update before close, which zaps VolCatInfo */ + Dmsg0(100, "dir_update_vol_info. Release0\n"); +- dir_update_volume_info(dcr, false); /* send Volume info to Director */ ++ dir_update_volume_info(dcr, false, false); /* send Volume info to Director */ + } + } + +@@ -621,7 +632,12 @@ + if (dcr->attached_to_dev) { + detach_dcr_from_dev(dcr); + } +- dcr->max_job_spool_size = dev->device->max_job_spool_size; ++ /* Use job spoolsize prior to device spoolsize */ ++ if (jcr->spool_size) { ++ dcr->max_job_spool_size = jcr->spool_size; ++ } else { ++ dcr->max_job_spool_size = dev->device->max_job_spool_size; ++ } + dcr->device = dev->device; + dcr->dev = dev; + attach_dcr_to_dev(dcr); +diff -ur k1/src/stored/askdir.c k3/src/stored/askdir.c +--- k1/src/stored/askdir.c 2007-09-09 12:03:23.000000000 +0200 ++++ k3/src/stored/askdir.c 2007-12-22 19:11:50.000000000 +0100 +@@ -31,7 +31,7 @@ + * + * Kern Sibbald, December 2000 + * +- * Version $Id: askdir.c 5503 2007-09-09 10:03:23Z kerns $ ++ * Version $Id: askdir.c 5852 2007-11-04 19:57:42Z kerns $ + */ + + #include "bacula.h" /* pull in global headers */ +@@ -42,7 +42,7 @@ + static char Get_Vol_Info[] = "CatReq Job=%s GetVolInfo VolName=%s write=%d\n"; + static char Update_media[] = "CatReq Job=%s UpdateMedia VolName=%s" + " VolJobs=%u VolFiles=%u VolBlocks=%u VolBytes=%s VolMounts=%u" +- " VolErrors=%u VolWrites=%u MaxVolBytes=%s EndTime=%d VolStatus=%s" ++ " VolErrors=%u VolWrites=%u MaxVolBytes=%s EndTime=%s VolStatus=%s" + " Slot=%d relabel=%d InChanger=%d VolReadTime=%s VolWriteTime=%s" + " VolFirstWritten=%s VolParts=%u\n"; + static char Create_job_media[] = "CatReq Job=%s CreateJobMedia" +@@ -98,7 +98,7 @@ + } else { + pm_strcpy(ChangerName, "*"); + } +- ok =bnet_fsend(dir, Device_update, ++ ok = dir->fsend(Device_update, + jcr->Job, + dev_name.c_str(), + dev->can_append()!=0, +@@ -125,7 +125,7 @@ + pm_strcpy(MediaType, device->media_type); + bash_spaces(MediaType); + /* This is mostly to indicate that we are here */ +- ok = bnet_fsend(dir, Device_update, ++ ok = dir->fsend(Device_update, + jcr->Job, + dev_name.c_str(), /* Changer name */ + 0, 0, 0, /* append, read, num_writers */ +@@ -148,7 +148,7 @@ + */ + bool dir_send_job_status(JCR *jcr) + { +- return bnet_fsend(jcr->dir_bsock, Job_status, jcr->Job, jcr->JobStatus); ++ return jcr->dir_bsock->fsend(Job_status, jcr->Job, jcr->JobStatus); + } + + /* +@@ -179,7 +179,7 @@ + return false; + } + memset(&vol, 0, sizeof(vol)); +- Dmsg1(100, "<dird %s\n", dir->msg); ++ Dmsg1(100, "<dird %s", dir->msg); + n = sscanf(dir->msg, OK_media, vol.VolCatName, + &vol.VolCatJobs, &vol.VolCatFiles, + &vol.VolCatBlocks, &vol.VolCatBytes, +@@ -191,7 +191,8 @@ + &vol.EndFile, &vol.EndBlock, &vol.VolCatParts, + &vol.LabelType, &vol.VolMediaId); + if (n != 22) { +- Dmsg3(100, "Bad response from Dir fields=%d, len=%d: %s", n, dir->msglen, dir->msg); ++ Dmsg3(100, "Bad response from Dir fields=%d, len=%d: %s", ++ n, dir->msglen, dir->msg); + Mmsg(jcr->errmsg, _("Error getting Volume info: %s"), dir->msg); + return false; + } +@@ -226,7 +227,7 @@ + bash_spaces(dcr->VolCatInfo.VolCatName); + dir->fsend(Get_Vol_Info, jcr->Job, dcr->VolCatInfo.VolCatName, + writing==GET_VOL_INFO_FOR_WRITE?1:0); +- Dmsg1(100, ">dird: %s\n", dir->msg); ++ Dmsg1(100, ">dird %s", dir->msg); + unbash_spaces(dcr->VolCatInfo.VolCatName); + bool ok = do_get_volume_info(dcr); + V(vol_info_mutex); +@@ -253,7 +254,9 @@ + BSOCK *dir = jcr->dir_bsock; + bool found = false; + +- Dmsg0(200, "dir_find_next_appendable_volume\n"); ++ Dmsg2(200, "dir_find_next_appendable_volume: reserved=%d Vol=%s\n", ++ dcr->reserved_device, dcr->VolumeName); ++ + /* + * Try the twenty oldest or most available volumes. Note, + * the most available could already be mounted on another +@@ -268,7 +271,7 @@ + dir->fsend(Find_media, jcr->Job, vol_index, dcr->pool_name, dcr->media_type); + unbash_spaces(dcr->media_type); + unbash_spaces(dcr->pool_name); +- Dmsg1(100, ">dird: %s", dir->msg); ++ Dmsg1(100, ">dird %s", dir->msg); + bool ok = do_get_volume_info(dcr); + if (ok) { + if (!is_volume_in_use(dcr)) { +@@ -311,14 +314,13 @@ + * back to the director. The information comes from the + * dev record. + */ +-bool dir_update_volume_info(DCR *dcr, bool label) ++bool dir_update_volume_info(DCR *dcr, bool label, bool update_LastWritten) + { + JCR *jcr = dcr->jcr; + BSOCK *dir = jcr->dir_bsock; + DEVICE *dev = dcr->dev; +- time_t LastWritten = time(NULL); + VOLUME_CAT_INFO *vol = &dev->VolCatInfo; +- char ed1[50], ed2[50], ed3[50], ed4[50], ed5[50]; ++ char ed1[50], ed2[50], ed3[50], ed4[50], ed5[50], ed6[50]; + int InChanger; + bool ok = false; + POOL_MEM VolumeName; +@@ -341,21 +343,25 @@ + if (label) { + bstrncpy(vol->VolCatStatus, "Append", sizeof(vol->VolCatStatus)); + } ++// if (update_LastWritten) { ++ vol->VolLastWritten = time(NULL); ++// } + pm_strcpy(VolumeName, vol->VolCatName); + bash_spaces(VolumeName); + InChanger = vol->InChanger; +- bnet_fsend(dir, Update_media, jcr->Job, ++ dir->fsend(Update_media, jcr->Job, + VolumeName.c_str(), vol->VolCatJobs, vol->VolCatFiles, + vol->VolCatBlocks, edit_uint64(vol->VolCatBytes, ed1), + vol->VolCatMounts, vol->VolCatErrors, + vol->VolCatWrites, edit_uint64(vol->VolCatMaxBytes, ed2), +- LastWritten, vol->VolCatStatus, vol->Slot, label, ++ edit_uint64(vol->VolLastWritten, ed6), ++ vol->VolCatStatus, vol->Slot, label, + InChanger, /* bool in structure */ + edit_int64(vol->VolReadTime, ed3), + edit_int64(vol->VolWriteTime, ed4), + edit_uint64(vol->VolFirstWritten, ed5), + vol->VolCatParts); +- Dmsg1(100, ">dird: %s", dir->msg); ++ Dmsg1(100, ">dird %s", dir->msg); + + /* Do not lock device here because it may be locked from label */ + if (!do_get_volume_info(dcr)) { +@@ -364,7 +370,7 @@ + vol->VolCatName, jcr->errmsg); + goto bail_out; + } +- Dmsg1(420, "get_volume_info(): %s", dir->msg); ++ Dmsg1(420, "get_volume_info() %s", dir->msg); + /* Update dev Volume info in case something changed (e.g. expired) */ + dev->VolCatInfo = dcr->VolCatInfo; + ok = true; +@@ -393,20 +399,20 @@ + } + + dcr->WroteVol = false; +- bnet_fsend(dir, Create_job_media, jcr->Job, ++ 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); ++ Dmsg1(100, ">dird %s", dir->msg); + if (bnet_recv(dir) <= 0) { + Dmsg0(190, "create_jobmedia error bnet_recv\n"); + Jmsg(jcr, M_FATAL, 0, _("Error creating JobMedia record: ERR=%s\n"), +- bnet_strerror(dir)); ++ dir->bstrerror()); + return false; + } +- Dmsg1(100, "<dir: %s", dir->msg); ++ Dmsg1(100, "<dird %s", dir->msg); + if (strcmp(dir->msg, OK_create) != 0) { + Dmsg1(130, "Bad response from Dir: %s\n", dir->msg); + Jmsg(jcr, M_FATAL, 0, _("Error creating JobMedia record: %s\n"), dir->msg); +@@ -429,9 +435,10 @@ + return true; + #endif + +- dir->msglen = sprintf(dir->msg, FileAttributes, jcr->Job); +- dir->msg = check_pool_memory_size(dir->msg, dir->msglen + +- sizeof(DEV_RECORD) + rec->data_len); ++ dir->msg = check_pool_memory_size(dir->msg, sizeof(FileAttributes) + ++ MAX_NAME_LENGTH + sizeof(DEV_RECORD) + rec->data_len + 1); ++ dir->msglen = bsnprintf(dir->msg, sizeof(FileAttributes) + ++ MAX_NAME_LENGTH + 1, FileAttributes, jcr->Job); + ser_begin(dir->msg + dir->msglen, 0); + ser_uint32(rec->VolSessionId); + ser_uint32(rec->VolSessionTime); +@@ -440,8 +447,8 @@ + ser_uint32(rec->data_len); + ser_bytes(rec->data, rec->data_len); + dir->msglen = ser_length(dir->msg); +- Dmsg1(1800, ">dird: %s\n", dir->msg); /* Attributes */ +- return bnet_send(dir); ++ Dmsg1(1800, ">dird %s\n", dir->msg); /* Attributes */ ++ return dir->send(); + } + + +diff -ur k1/src/stored/bcopy.c k3/src/stored/bcopy.c +--- k1/src/stored/bcopy.c 2007-12-03 20:27:38.000000000 +0100 ++++ k3/src/stored/bcopy.c 2007-12-22 19:10:29.000000000 +0100 +@@ -32,7 +32,7 @@ + * Kern E. Sibbald, October 2002 + * + * +- * Version $Id: bcopy.c 6017 2007-12-03 19:27:38Z kerns $ ++ * Version $Id: bcopy.c 6016 2007-12-03 19:27:21Z kerns $ + */ + + #include "bacula.h" +@@ -42,6 +42,7 @@ + int generate_daemon_event(JCR *jcr, const char *event) { return 1; } + + /* Forward referenced functions */ ++static void get_session_record(DEVICE *dev, DEV_RECORD *rec, SESSION_LABEL *sessrec); + static bool record_cb(DCR *dcr, DEV_RECORD *rec); + + +@@ -52,10 +53,11 @@ + static JCR *out_jcr; /* output jcr */ + static BSR *bsr = NULL; + static const char *wd = "/tmp"; +-static int list_records = 0; ++static bool list_records = false; + static uint32_t records = 0; + static uint32_t jobs = 0; + static DEV_BLOCK *out_block; ++static SESSION_LABEL sessrec; + + #define CONFIG_FILE "bacula-sd.conf" + char *configfile = NULL; +@@ -73,7 +75,7 @@ + "Usage: bcopy [-d debug_level] <input-archive> <output-archive>\n" + " -b bootstrap specify a bootstrap file\n" + " -c <file> specify configuration file\n" +-" -d <nn> set debug level to nn\n" ++" -d <nn> set debug level to <nn>\n" + " -i specify input Volume names (separated by |)\n" + " -o specify output Volume names (separated by |)\n" + " -p proceed inspite of errors\n" +@@ -113,9 +115,14 @@ + break; + + case 'd': /* debug level */ +- debug_level = atoi(optarg); +- if (debug_level <= 0) +- debug_level = 1; ++ if (*optarg == 't') { ++ dbg_timestamp = true; ++ } else { ++ debug_level = atoi(optarg); ++ if (debug_level <= 0) { ++ debug_level = 1; ++ } ++ } + break; + + case 'i': /* input Volume name */ +@@ -201,6 +208,7 @@ + out_block = out_jcr->dcr->block; + + ok = read_records(in_jcr->dcr, record_cb, mount_next_read_volume); ++ + if (ok || out_dev->can_write()) { + if (!write_block_to_device(out_jcr->dcr)) { + Pmsg0(000, _("Write of last block failed.\n")); +@@ -233,6 +241,7 @@ + * + */ + if (rec->FileIndex < 0) { ++ get_session_record(in_dcr->dev, rec, &sessrec); + + if (verbose > 1) { + dump_label_record(in_dcr->dev, rec, 1); +@@ -294,10 +303,46 @@ + return true; + } + ++static void get_session_record(DEVICE *dev, DEV_RECORD *rec, SESSION_LABEL *sessrec) ++{ ++ const char *rtype; ++ memset(sessrec, 0, sizeof(sessrec)); ++ switch (rec->FileIndex) { ++ case PRE_LABEL: ++ rtype = _("Fresh Volume Label"); ++ break; ++ case VOL_LABEL: ++ rtype = _("Volume Label"); ++ unser_volume_label(dev, rec); ++ break; ++ case SOS_LABEL: ++ rtype = _("Begin Job Session"); ++ unser_session_label(sessrec, rec); ++ break; ++ case EOS_LABEL: ++ rtype = _("End Job Session"); ++ unser_session_label(sessrec, rec); ++ break; ++ case 0: ++ case EOM_LABEL: ++ rtype = _("End of Medium"); ++ break; ++ default: ++ rtype = _("Unknown"); ++ break; ++ } ++ Dmsg5(10, "%s Record: VolSessionId=%d VolSessionTime=%d JobId=%d DataLen=%d\n", ++ rtype, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len); ++ if (verbose) { ++ Pmsg5(-1, _("%s Record: VolSessionId=%d VolSessionTime=%d JobId=%d DataLen=%d\n"), ++ rtype, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len); ++ } ++} ++ + + /* Dummies to replace askdir.c */ + bool dir_find_next_appendable_volume(DCR *dcr) { return 1;} +-bool dir_update_volume_info(DCR *dcr, bool relabel) { return 1; } ++bool dir_update_volume_info(DCR *dcr, bool relabel, bool update_LastWritten) { return 1; } + bool dir_create_jobmedia_record(DCR *dcr) { return 1; } + bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr) { return 1; } + bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec) { return 1;} +diff -ur k1/src/stored/bextract.c k3/src/stored/bextract.c +--- k1/src/stored/bextract.c 2007-10-03 13:36:47.000000000 +0200 ++++ k3/src/stored/bextract.c 2007-12-22 19:10:20.000000000 +0100 +@@ -4,7 +4,7 @@ + * + * Kern E. Sibbald, MM + * +- * Version $Id: bextract.c 5713 2007-10-03 11:36:47Z kerns $ ++ * Version $Id: bextract.c 5852 2007-11-04 19:57:42Z kerns $ + * + */ + /* +@@ -79,7 +79,7 @@ + "Usage: bextract <options> <bacula-archive-device-name> <directory-to-store-files>\n" + " -b <file> specify a bootstrap file\n" + " -c <file> specify a configuration file\n" +-" -d <nn> set debug level to nn\n" ++" -d <nn> set debug level to <nn>\n" + " -e <file> exclude list\n" + " -i <file> include list\n" + " -p proceed inspite of I/O errors\n" +@@ -126,9 +126,14 @@ + break; + + case 'd': /* debug level */ +- debug_level = atoi(optarg); +- if (debug_level <= 0) +- debug_level = 1; ++ if (*optarg == 't') { ++ dbg_timestamp = true; ++ } else { ++ debug_level = atoi(optarg); ++ if (debug_level <= 0) { ++ debug_level = 1; ++ } ++ } + break; + + case 'e': /* exclude list */ +@@ -476,7 +481,7 @@ + + /* Dummies to replace askdir.c */ + bool dir_find_next_appendable_volume(DCR *dcr) { return 1;} +-bool dir_update_volume_info(DCR *dcr, bool relabel) { return 1; } ++bool dir_update_volume_info(DCR *dcr, bool relabel, bool update_LastWritten) { return 1; } + bool dir_create_jobmedia_record(DCR *dcr) { return 1; } + bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr) { return 1; } + bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec) { return 1;} +diff -ur k1/src/stored/block.c k3/src/stored/block.c +--- k1/src/stored/block.c 2007-10-03 13:36:47.000000000 +0200 ++++ k3/src/stored/block.c 2007-12-22 19:12:33.000000000 +0100 +@@ -32,7 +32,7 @@ + * Kern Sibbald, March MMI + * added BB02 format October MMII + * +- * Version $Id: block.c 5713 2007-10-03 11:36:47Z kerns $ ++ * Version $Id: block.c 5852 2007-11-04 19:57:42Z kerns $ + * + */ + +@@ -746,7 +746,7 @@ + dev->VolCatInfo.VolCatParts = dev->num_dvd_parts; + } + +- if (!dir_update_volume_info(dcr, false)) { ++ if (!dir_update_volume_info(dcr, false, true)) { + ok = false; + } + Dmsg1(100, "dir_update_volume_info terminate writing -- %s\n", ok?"OK":"ERROR"); +@@ -798,7 +798,7 @@ + return false; + } + dev->VolCatInfo.VolCatFiles = dev->file; +- if (!dir_update_volume_info(dcr, false)) { ++ if (!dir_update_volume_info(dcr, false, false)) { + Dmsg0(190, "Error from update_vol_info.\n"); + terminate_writing_volume(dcr); + dev->dev_errno = EIO; +@@ -856,7 +856,7 @@ + + dev->VolCatInfo.VolCatParts = dev->num_dvd_parts; + +- if (!dir_update_volume_info(dcr, false)) { ++ if (!dir_update_volume_info(dcr, false, false)) { + Dmsg0(190, "Error from update_vol_info.\n"); + dev->dev_errno = EIO; + return false; +diff -ur k1/src/stored/bls.c k3/src/stored/bls.c +--- k1/src/stored/bls.c 2007-10-03 13:36:47.000000000 +0200 ++++ k3/src/stored/bls.c 2007-12-22 19:10:57.000000000 +0100 +@@ -31,7 +31,7 @@ + * + * Kern Sibbald, MM + * +- * Version $Id: bls.c 5713 2007-10-03 11:36:47Z kerns $ ++ * Version $Id: bls.c 5852 2007-11-04 19:57:42Z kerns $ + */ + + #include "bacula.h" +@@ -79,7 +79,7 @@ + "Usage: bls [options] <device-name>\n" + " -b <file> specify a bootstrap file\n" + " -c <file> specify a config file\n" +-" -d <level> specify debug level\n" ++" -d <nn> set debug level to <nn>\n" + " -e <file> exclude list\n" + " -i <file> include list\n" + " -j list jobs\n" +@@ -130,9 +130,14 @@ + break; + + case 'd': /* debug level */ +- debug_level = atoi(optarg); +- if (debug_level <= 0) +- debug_level = 1; ++ if (*optarg == 't') { ++ dbg_timestamp = true; ++ } else { ++ debug_level = atoi(optarg); ++ if (debug_level <= 0) { ++ debug_level = 1; ++ } ++ } + break; + + case 'e': /* exclude list */ +@@ -440,7 +445,7 @@ + + /* Dummies to replace askdir.c */ + bool dir_find_next_appendable_volume(DCR *dcr) { return 1;} +-bool dir_update_volume_info(DCR *dcr, bool relabel) { return 1; } ++bool dir_update_volume_info(DCR *dcr, bool relabel, bool update_LastWritten) { return 1; } + bool dir_create_jobmedia_record(DCR *dcr) { return 1; } + bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr) { return 1; } + bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec) { return 1;} +diff -ur k1/src/stored/bscan.c k3/src/stored/bscan.c +--- k1/src/stored/bscan.c 2007-10-03 13:36:47.000000000 +0200 ++++ k3/src/stored/bscan.c 2007-12-22 19:11:05.000000000 +0100 +@@ -34,7 +34,7 @@ + * Kern E. Sibbald, December 2001 + * + * +- * Version $Id: bscan.c 5713 2007-10-03 11:36:47Z kerns $ ++ * Version $Id: bscan.c 5852 2007-11-04 19:57:42Z kerns $ + */ + + #include "bacula.h" +@@ -116,7 +116,7 @@ + "Usage: bscan [ options ] <bacula-archive>\n" + " -b bootstrap specify a bootstrap file\n" + " -c <file> specify configuration file\n" +-" -d <nn> set debug level to nn\n" ++" -d <nn> set debug level to <nn>\n" + " -m update media info in database\n" + " -n <name> specify the database name (default bacula)\n" + " -u <user> specify database user name (default bacula)\n" +@@ -166,9 +166,14 @@ + break; + + case 'd': /* debug level */ +- debug_level = atoi(optarg); +- if (debug_level <= 0) +- debug_level = 1; ++ if (*optarg == 't') { ++ dbg_timestamp = true; ++ } else { ++ debug_level = atoi(optarg); ++ if (debug_level <= 0) { ++ debug_level = 1; ++ } ++ } + break; + + case 'h': +@@ -1271,7 +1276,7 @@ + + /* Dummies to replace askdir.c */ + bool dir_find_next_appendable_volume(DCR *dcr) { return 1;} +-bool dir_update_volume_info(DCR *dcr, bool relabel) { return 1; } ++bool dir_update_volume_info(DCR *dcr, bool relabel, bool update_LastWritten) { return 1; } + bool dir_create_jobmedia_record(DCR *dcr) { return 1; } + bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr) { return 1; } + bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec) { return 1;} +diff -ur k1/src/stored/btape.c k3/src/stored/btape.c +--- k1/src/stored/btape.c 2007-06-07 16:46:43.000000000 +0200 ++++ k3/src/stored/btape.c 2007-12-22 19:11:14.000000000 +0100 +@@ -37,7 +37,7 @@ + * Note, this program reads stored.conf, and will only + * talk to devices that are configured. + * +- * Version $Id: btape.c 4992 2007-06-07 14:46:43Z kerns $ ++ * Version $Id: btape.c 5852 2007-11-04 19:57:42Z kerns $ + * + */ + +@@ -220,9 +220,13 @@ + break; + + case 'd': /* set debug level */ +- debug_level = atoi(optarg); +- if (debug_level <= 0) { +- debug_level = 1; ++ if (*optarg == 't') { ++ dbg_timestamp = true; ++ } else { ++ debug_level = atoi(optarg); ++ if (debug_level <= 0) { ++ debug_level = 1; ++ } + } + break; + +@@ -2598,7 +2602,7 @@ + "Usage: btape <options> <device_name>\n" + " -b <file> specify bootstrap file\n" + " -c <file> set configuration file to file\n" +-" -d <nn> set debug level to nn\n" ++" -d <nn> set debug level to <nn>\n" + " -p proceed inspite of I/O errors\n" + " -s turn off signals\n" + " -v be verbose\n" +@@ -2644,7 +2648,7 @@ + bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec) { return 1;} + bool dir_send_job_status(JCR *jcr) {return 1;} + +-bool dir_update_volume_info(DCR *dcr, bool relabel) ++bool dir_update_volume_info(DCR *dcr, bool relabel, bool update_LastWritten) + { + return 1; + } +diff -ur k1/src/stored/dev.c k3/src/stored/dev.c +--- k1/src/stored/dev.c 2007-12-02 19:03:17.000000000 +0100 ++++ k3/src/stored/dev.c 2007-12-22 19:11:57.000000000 +0100 +@@ -47,7 +47,7 @@ + * daemon. More complicated coding (double buffering, writer + * thread, ...) is left for a later version. + * +- * Version $Id: dev.c 6011 2007-12-02 18:03:17Z kerns $ ++ * Version $Id: dev.c 5999 2007-11-29 21:36:36Z ricozz $ + */ + + /* +@@ -89,7 +89,7 @@ + /* Forward referenced functions */ + void set_os_device_parameters(DCR *dcr); + static bool dev_get_os_pos(DEVICE *dev, struct mtget *mt_stat); +-static char *mode_to_str(int mode); ++static const char *mode_to_str(int mode); + + /* + * Allocate and initialize the DEVICE structure +@@ -490,7 +490,7 @@ + Mmsg2(errmsg, _("Could not open: %s, ERR=%s\n"), archive_name.c_str(), + be.bstrerror()); + Dmsg1(100, "open failed: %s", errmsg); +- Emsg0(M_FATAL, 0, errmsg); ++ Jmsg1(NULL, M_WARNING, 0, "%s", errmsg); + } else { + dev_errno = 0; + file = 0; +@@ -2468,7 +2468,7 @@ + mt_stat->mt_fileno >= 0; + } + +-static char *modes[] = { ++static const char *modes[] = { + "CREATE_READ_WRITE", + "OPEN_READ_WRITE", + "OPEN_READ_ONLY", +@@ -2476,7 +2476,7 @@ + }; + + +-static char *mode_to_str(int mode) ++static const char *mode_to_str(int mode) + { + static char buf[100]; + if (mode < 1 || mode > 4) { +diff -ur k1/src/stored/dev.h k3/src/stored/dev.h +--- k1/src/stored/dev.h 2007-09-09 12:03:23.000000000 +0200 ++++ k3/src/stored/dev.h 2007-12-22 19:12:14.000000000 +0100 +@@ -31,7 +31,7 @@ + * + * Kern Sibbald, MM + * +- * Version $Id: dev.h 5503 2007-09-09 10:03:23Z kerns $ ++ * Version $Id: dev.h 5852 2007-11-04 19:57:42Z kerns $ + * + */ + +@@ -158,6 +158,7 @@ + btime_t VolWriteTime; /* time spent writing this Volume */ + int64_t VolMediaId; /* MediaId */ + utime_t VolFirstWritten; /* Time of first write */ ++ utime_t VolLastWritten; /* Time of last write */ + bool InChanger; /* Set if vol in current magazine */ + char VolCatStatus[20]; /* Volume status */ + char VolCatName[MAX_NAME_LENGTH]; /* Desired volume to mount */ +@@ -473,8 +474,9 @@ + class VOLRES { + public: + dlink link; +- char *vol_name; +- DEVICE *dev; ++ char *vol_name; /* Volume name */ ++ DEVICE *dev; /* Pointer to device to which we are attached */ ++ bool released; /* set when the Volume can be released */ + }; + + +diff -ur k1/src/stored/device.c k3/src/stored/device.c +--- k1/src/stored/device.c 2007-06-29 14:12:26.000000000 +0200 ++++ k3/src/stored/device.c 2007-12-22 19:11:23.000000000 +0100 +@@ -53,7 +53,7 @@ + * + * Kern Sibbald, MM, MMI + * +- * Version $Id: device.c 5114 2007-06-29 12:12:26Z kerns $ ++ * Version $Id: device.c 5852 2007-11-04 19:57:42Z kerns $ + */ + + #include "bacula.h" /* pull in global headers */ +@@ -122,7 +122,8 @@ + edit_uint64_with_commas(dev->VolCatInfo.VolCatBlocks, b2), + bstrftime(dt, sizeof(dt), time(NULL))); + +- if (!mount_next_write_volume(dcr, 1)) { ++ /* Called with have_vol=false, release=true */ ++ if (!mount_next_write_volume(dcr, false, true)) { + free_block(label_blk); + dcr->block = block; + dev->dlock(); +@@ -131,7 +132,7 @@ + dev->dlock(); /* lock again */ + + dev->VolCatInfo.VolCatJobs++; /* increment number of jobs on vol */ +- dir_update_volume_info(dcr, false); /* send Volume info to Director */ ++ dir_update_volume_info(dcr, false, false); /* send Volume info to Director */ + + Jmsg(jcr, M_INFO, 0, _("New volume \"%s\" mounted on device %s at %s.\n"), + dcr->VolumeName, dev->print_name(), bstrftime(dt, sizeof(dt), time(NULL))); +diff -ur k1/src/stored/dvd.c k3/src/stored/dvd.c +--- k1/src/stored/dvd.c 2007-06-07 16:46:43.000000000 +0200 ++++ k3/src/stored/dvd.c 2007-12-22 19:26:23.000000000 +0100 +@@ -1,16 +1,7 @@ + /* +- * +- * dvd.c -- Routines specific to DVD devices (and +- * possibly other removable hard media). +- * +- * Nicolas Boichat, MMV +- * +- * Version $Id: dvd.c 4992 2007-06-07 14:46:43Z kerns $ +- */ +-/* + Bacula® - The Network Backup Solution + +- Copyright (C) 2005-2006 Free Software Foundation Europe e.V. ++ Copyright (C) 2005-2007 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. +@@ -34,6 +25,15 @@ + (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, + Switzerland, email:ft...@fs.... + */ ++/* ++ * ++ * dvd.c -- Routines specific to DVD devices (and ++ * possibly other removable hard media). ++ * ++ * Nicolas Boichat, MMV ++ * ++ * Version $Id: dvd.c 5852 2007-11-04 19:57:42Z kerns $ ++ */ + + #include "bacula.h" + #include "stored.h" +@@ -686,7 +686,7 @@ + dcr->VolCatInfo.VolCatBytes = 0; + + /* Update catalog */ +- if (!dir_update_volume_info(dcr, false)) { ++ if (!dir_update_volume_info(dcr, false, true)) { + return false; + } + +diff -ur k1/src/stored/job.c k3/src/stored/job.c +--- k1/src/stored/job.c 2007-09-29 00:01:16.000000000 +0200 ++++ k3/src/stored/job.c 2007-12-22 19:11:41.000000000 +0100 +@@ -30,7 +30,7 @@ + * + * Kern Sibbald, MM + * +- * Version $Id: job.c 5686 2007-09-28 22:01:16Z kerns $ ++ * Version $Id: job.c 5697 2007-09-30 17:40:08Z ricozz $ + * + */ + +@@ -49,9 +49,13 @@ + /* Requests from the Director daemon */ + static char jobcmd[] = "JobId=%d job=%127s job_name=%127s client_name=%127s " + "type=%d level=%d FileSet=%127s NoAttr=%d SpoolAttr=%d FileSetMD5=%127s " ++ "SpoolData=%d WritePartAfterJob=%d PreferMountedVols=%d SpoolSize=%s\n"; ++static char oldjobcmd[] = "JobId=%d job=%127s job_name=%127s client_name=%127s " ++ "type=%d level=%d FileSet=%127s NoAttr=%d SpoolAttr=%d FileSetMD5=%127s " + "SpoolData=%d WritePartAfterJob=%d PreferMountedVols=%d\n"; + + ++ + /* Responses sent to Director daemon */ + static char OKjob[] = "3000 OK Job SDid=%u SDtime=%u Authorization=%s\n"; + static char BAD_job[] = "3915 Bad Job command. stat=%d CMD: %s\n"; +@@ -73,6 +77,7 @@ + { + int JobId; + char auth_key[100]; ++ char spool_size[30]; + char seed[100]; + BSOCK *dir = jcr->dir_bsock; + POOL_MEM job_name, client_name, job, fileset_name, fileset_md5; +@@ -85,17 +90,26 @@ + * Get JobId and permissions from Director + */ + Dmsg1(100, "<dird: %s", dir->msg); ++ bstrncpy(spool_size, "0", sizeof(spool_size)); + stat = sscanf(dir->msg, jobcmd, &JobId, job.c_str(), job_name.c_str(), + client_name.c_str(), + &JobType, &level, fileset_name.c_str(), &no_attributes, +- &spool_attributes, fileset_md5.c_str(), &spool_data, ++ &spool_attributes, fileset_md5.c_str(), &spool_data, ++ &write_part_after_job, &PreferMountedVols, spool_size); ++ if (stat != 14) { ++ /* Try old version */ ++ stat = sscanf(dir->msg, oldjobcmd, &JobId, job.c_str(), job_name.c_str(), ++ client_name.c_str(), ++ &JobType, &level, fileset_name.c_str(), &no_attributes, ++ &spool_attributes, fileset_md5.c_str(), &spool_data, + &write_part_after_job, &PreferMountedVols); +- if (stat != 13) { +- pm_strcpy(jcr->errmsg, dir->msg); +- dir->fsend(BAD_job, stat, jcr->errmsg); +- Dmsg1(100, ">dird: %s", dir->msg); +- set_jcr_job_status(jcr, JS_ErrorTerminated); +- return false; ++ if (stat != 13) { ++ pm_strcpy(jcr->errmsg, dir->msg); ++ dir->fsend(BAD_job, stat, jcr->errmsg); ++ Dmsg1(100, ">dird: %s", dir->msg); ++ set_jcr_job_status(jcr, JS_ErrorTerminated); ++ return false; ++ } + } + /* + * Since this job could be rescheduled, we +@@ -125,6 +139,7 @@ + jcr->no_attributes = no_attributes; + jcr->spool_attributes = spool_attributes; + jcr->spool_data = spool_data; ++ jcr->spool_size = str_to_int64(spool_size); + jcr->write_part_after_job = write_part_after_job; + jcr->fileset_md5 = get_pool_memory(PM_NAME); + pm_strcpy(jcr->fileset_md5, fileset_md5); +diff -ur k1/src/stored/label.c k3/src/stored/label.c +--- k1/src/stored/label.c 2007-10-03 13:36:47.000000000 +0200 ++++ k3/src/stored/label.c 2007-12-22 19:10:49.000000000 +0100 +@@ -32,7 +32,7 @@ + * Kern Sibbald, MM + * + * +- * Version $Id: label.c 5713 2007-10-03 11:36:47Z kerns $ ++ * Version $Id: label.c 5852 2007-11-04 19:57:42Z kerns $ + */ + + #include "bacula.h" /* pull in global headers */ +@@ -505,7 +505,7 @@ + } + Dmsg0(150, "dir_update_vol_info. Set Append\n"); + bstrncpy(dev->VolCatInfo.VolCatStatus, "Append", sizeof(dev->VolCatInfo.VolCatStatus)); +- if (!dir_update_volume_info(dcr, true)) { /* indicate doing relabel */ ++ if (!dir_update_volume_info(dcr, true, true)) { /* indicate doing relabel */ + return false; + } + if (recycle) { +@@ -716,7 +716,7 @@ + } + break; + default: +- Jmsg1(jcr, M_ABORT, 0, _("Bad session label = %d\n"), label); ++ Jmsg1(jcr, M_ABORT, 0, _("Bad Volume session label = %d\n"), label); + break; + } + create_session_label(dcr, rec, label); +diff -ur k1/src/stored/mount.c k3/src/stored/mount.c +--- k1/src/stored/mount.c 2007-09-14 11:49:06.000000000 +0200 ++++ k3/src/stored/mount.c 2007-12-22 19:11:30.000000000 +0100 +@@ -32,7 +32,7 @@ + * + * Kern Sibbald, August MMII + * +- * Version $Id: mount.c 5552 2007-09-14 09:49:06Z kerns $ ++ * Version $Id: mount.c 5852 2007-11-04 19:57:42Z kerns $ + */ + + #include "bacula.h" /* pull in global headers */ +@@ -60,7 +60,7 @@ + * impossible to get the requested Volume. + * + */ +-bool mount_next_write_volume(DCR *dcr, bool release) ++bool mount_next_write_volume(DCR *dcr, bool have_vol, bool release) + { + int retry = 0; + bool ask = false, recycle, autochanger; +@@ -108,12 +108,16 @@ + * in dcr->VolCatInfo + */ + Dmsg0(200, "Before dir_find_next_appendable_volume.\n"); +- while (!dir_find_next_appendable_volume(dcr)) { +- Dmsg0(200, "not dir_find_next\n"); +- if (!dir_ask_sysop_to_create_appendable_volume(dcr)) { +- return false; ++ if (!have_vol) { ++ while (!dir_find_next_appendable_volume(dcr)) { ++ Dmsg0(200, "not dir_find_next\n"); ++ if (!dir_ask_sysop_to_create_appendable_volume(dcr)) { ++ return false; ++ } ++ Dmsg0(200, "Again dir_find_next_append...\n"); + } +- Dmsg0(200, "Again dir_find_next_append...\n"); ++ } else { ++ have_vol = false; /* set false for next pass if any */ + } + if (job_canceled(jcr)) { + return false; +@@ -144,7 +148,7 @@ + * If we autochanged to correct Volume or (we have not just + * released the Volume AND we can automount) we go ahead + * and read the label. If there is no tape in the drive, +- * we will err, recurse and ask the operator the next time. ++ * we will fail, recurse and ask the operator the next time. + */ + if (!release && dev->is_tape() && dev->has_cap(CAP_AUTOMOUNT)) { + Dmsg0(150, "(1)Ask=0\n"); +@@ -432,7 +436,7 @@ + } + dev->VolCatInfo.VolCatMounts++; /* Update mounts */ + Dmsg1(150, "update volinfo mounts=%d\n", dev->VolCatInfo.VolCatMounts); +- if (!dir_update_volume_info(dcr, false)) { ++ if (!dir_update_volume_info(dcr, false, false)) { + return false; + } + +@@ -519,7 +523,7 @@ + Dmsg0(150, "dir_update_vol_info. Set Append\n"); + /* Copy Director's info into the device info */ + dev->VolCatInfo = dcr->VolCatInfo; /* structure assignment */ +- if (!dir_update_volume_info(dcr, true)) { /* indicate tape labeled */ ++ if (!dir_update_volume_info(dcr, true, true)) { /* indicate tape labeled */ + return try_error; + } + Jmsg(dcr->jcr, M_INFO, 0, _("Labeled new Volume \"%s\" on device %s.\n"), +@@ -552,7 +556,7 @@ + dev->VolCatInfo = dcr->VolCatInfo; /* structure assignment */ + bstrncpy(dev->VolCatInfo.VolCatStatus, "Error", sizeof(dev->VolCatInfo.VolCatStatus)); + Dmsg0(150, "dir_update_vol_info. Set Error.\n"); +- dir_update_volume_info(dcr, false); ++ dir_update_volume_info(dcr, false, false); + } + + /* +@@ -570,7 +574,7 @@ + dcr->VolCatInfo.InChanger = false; + dev->VolCatInfo.InChanger = false; + Dmsg0(400, "update vol info in mount\n"); +- dir_update_volume_info(dcr, true); /* set new status */ ++ dir_update_volume_info(dcr, true, false); /* set new status */ + } + + /* +@@ -588,6 +592,7 @@ + /* + * First erase all memory of the current volume + */ ++ free_volume(dev); + dev->block_num = dev->file = 0; + dev->EndBlock = dev->EndFile = 0; + memset(&dev->VolCatInfo, 0, sizeof(dev->VolCatInfo)); +diff -ur k1/src/stored/protos.h k3/src/stored/protos.h +--- k1/src/stored/protos.h 2007-06-28 13:57:03.000000000 +0200 ++++ k3/src/stored/protos.h 2007-12-22 19:12:43.000000000 +0100 +@@ -28,7 +28,7 @@ + /* + * Protypes for stored -- Kern Sibbald MM + * +- * Version $Id: protos.h 5112 2007-06-28 11:57:03Z kerns $ ++ * Version $Id: protos.h 5852 2007-11-04 19:57:42Z kerns $ + */ + + /* From stored.c */ +@@ -49,7 +49,7 @@ + }; + bool dir_get_volume_info(DCR *dcr, enum get_vol_info_rw); + bool dir_find_next_appendable_volume(DCR *dcr); +-bool dir_update_volume_info(DCR *dcr, bool label); ++bool dir_update_volume_info(DCR *dcr, bool label, bool update_LastWritten); + bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr); + bool dir_ask_sysop_to_mount_volume(DCR *dcr); + bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec); +@@ -182,7 +182,7 @@ + bool is_this_bsr_done(BSR *bsr, DEV_RECORD *rec); + + /* From mount.c */ +-bool mount_next_write_volume(DCR *dcr, bool release); ++bool mount_next_write_volume(DCR *dcr, bool have_vol, bool release); + bool mount_next_read_volume(DCR *dcr); + void mark_volume_in_error(DCR *dcr); + +diff -ur k1/src/stored/record.c k3/src/stored/record.c +--- k1/src/stored/record.c 2007-06-07 16:46:43.000000000 +0200 ++++ k3/src/stored/record.c 2007-12-22 19:12:06.000000000 +0100 +@@ -1,14 +1,4 @@ + /* +- * +- * record.c -- tape record handling functions +- * +- * Kern Sibbald, April MMI +- * added BB02 format October MMII +- * +- * Version $Id: record.c 4992 2007-06-07 14:46:43Z kerns $ +- * +- */ +-/* + Bacula® - The Network Backup Solution + + Copyright (C) 2001-2006 Free Software Foundation Europe e.V. +@@ -35,6 +25,16 @@ + (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, + Switzerland, email:ft...@fs.... + */ ++/* ++ * ++ * record.c -- tape record handling functions ++ * ++ * Kern Sibbald, April MMI ++ * added BB02 format October MMII ++ * ++ * Version $Id: record.c 6014 2007-12-03 18:14:27Z kerns $ ++ * ++ */ + + + #include "bacula.h" +@@ -254,7 +254,7 @@ + ASSERT(block->buf_len >= block->binbuf); + + Dmsg6(890, "write_record_to_block() FI=%s SessId=%d Strm=%s len=%d\n" +-"rem=%d remainder=%d\n", ++ "rem=%d remainder=%d\n", + FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId, + stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len, + remlen, rec->remainder); +@@ -365,7 +365,7 @@ + if (!sm_check_rtn(__FILE__, __LINE__, False)) { + /* We damaged a buffer */ + Dmsg6(0, "Damaged block FI=%s SessId=%d Strm=%s len=%d\n" +-"rem=%d remainder=%d\n", ++ "rem=%d remainder=%d\n", + FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId, + stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len, + remlen, rec->remainder); +diff -ur k1/src/stored/reserve.c k3/src/stored/reserve.c +--- k1/src/stored/reserve.c 2007-08-04 18:46:32.000000000 +0200 ++++ k3/src/stored/reserve.c 2007-12-22 19:09:56.000000000 +0100 +@@ -212,11 +212,11 @@ + if (dev) { + len = Mmsg(msg, "%s on device %s\n", vol->vol_name, dev->print_name()); + sendit(msg.c_str(), len, arg); +- len = Mmsg(msg, " Reader=%d writers=%d reserved=%d\n", dev->can_read()?1:0, +- dev->num_writers, dev->reserved_device); ++ len = Mmsg(msg, " Reader=%d writers=%d reserved=%d released=%d\n", ++ dev->can_read()?1:0, dev->num_writers, dev->reserved_device, vol->released); + sendit(msg.c_str(), len, arg); + } else { +- len = Mmsg(msg, "%s no dev\n", vol->vol_name); ++ len = Mmsg(msg, "%s no device. released=%d\n", vol->vol_name, vol->released); + sendit(msg.c_str(), len, arg); + } + } +@@ -292,11 +292,11 @@ + * already exist and are correctly programmed and will need no changes -- use + * counts are always very tricky. + * +- * The old code had a concept of "reserving" a Volume, but it needs to be changed ++ * The old code had a concept of "reserving" a Volume, but was changed + * to reserving and using a drive. A volume is must be attached to (owned by) a + * drive and can move from drive to drive or be unused given certain specific + * conditions of the drive. The key is that the drive must "own" the Volume. +- * The old code has the job (dcr) owning the volume (more or less). The job is ++ * The old code had the job (dcr) owning the volume (more or less). The job was + * to change the insertion and removal of the volumes from the list to be based + * on the drive rather than the job. + * +@@ -329,13 +329,14 @@ + * because it was probably inserted by another job. + */ + if (strcmp(vol->vol_name, VolumeName) == 0) { ++ Dmsg1(dbglvl, "OK, vol=%s on device.\n", VolumeName); + goto get_out; /* Volume already on this device */ + } else { +- Dmsg3(dbglvl, "jid=%u reserve_vol free vol=%s at %p\n", ++ Dmsg3(dbglvl, "jid=%u reserve_vol free vol=%s at %p\n", + (int)dcr->jcr->JobId, vol->vol_name, vol->vol_name); +- debug_list_volumes("reserve_vol free"); + vol_list->remove(vol); + free_vol_item(vol); ++ debug_list_volumes("reserve_vol free"); + } + } + +@@ -378,12 +379,16 @@ + Dmsg4(dbglvl, "jid=%u Volume busy could not swap vol=%s from dev=%s to %s\n", + jid(), VolumeName, vol->dev->print_name(), dev->print_name()); + vol = NULL; /* device busy */ ++ goto get_out; + } + } + } + dev->vol = vol; + + get_out: ++ if (vol) { ++ vol->released = false; ++ } + debug_list_volumes("end new volume"); + unlock_volumes(); + return vol; +@@ -462,6 +467,7 @@ + * explicitly read in this drive. This allows the SD to remember + * where the tapes are or last were. + */ ++ dev->vol->released = true; + if (dev->is_tape() || dev->is_autochanger()) { + return true; + } else { +@@ -837,6 +843,7 @@ + dlist *temp_vol_list, *save_vol_list; + VOLR... [truncated message content] |