not have to upgrade all your File daemons when you upgrade. There is
no database upgrade needed from version 2.0.x to 2.2.0.
-Version 2.2.7 has several new features and several importatn bug fixes
+Version 2.2.7 has several new features and several important bug fixes
since version 2.2.6:
- It fixes bugs: 1009, 1022, 1024, 1019, 1012, 1021, 1020
1007, 1008. For more details, please see the technotes-2.1 file.
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-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.
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 */
-/*
- * Define Message Types for Bacula
- * Kern Sibbald, 2000
- *
- * Version $Id$
- */
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-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.
(FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
Switzerland, email:ftf@fsfeurope.org.
*/
+/*
+ * Define Message Types for Bacula
+ * Kern Sibbald, 2000
+ *
+ * Version $Id$
+ */
#include "bits.h"
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;
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2002-2007 Free Software Foundation Europe e.V.
+ Copyright (C) 2002-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.
/* Forward referenced functions */
static void attach_dcr_to_dev(DCR *dcr);
+static bool is_suitable_volume_mounted(DCR *dcr);
/*********************************************************************
*/
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;
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");
/*
* 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 {
* 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));
}
}
} 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;
}
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);
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);
}
+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.
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) {
/*
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 */
}
}
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);
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-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.
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"
} 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,
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 */
*/
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);
}
/*
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,
&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;
}
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);
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
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)) {
* 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;
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)) {
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;
}
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);
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);
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();
}
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2002-2007 Free Software Foundation Europe e.V.
+ Copyright (C) 2002-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.
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);
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;
"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"
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 */
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"));
*
*/
if (rec->FileIndex < 0) {
+ get_session_record(in_dcr->dev, rec, &sessrec);
if (verbose > 1) {
dump_label_record(in_dcr->dev, rec, 1);
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;}
-/*
- *
- * Dumb program to extract files from a Bacula backup.
- *
- * Kern E. Sibbald, MM
- *
- * Version $Id$
- *
- */
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-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.
(FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
Switzerland, email:ftf@fsfeurope.org.
*/
+/*
+ *
+ * Dumb program to extract files from a Bacula backup.
+ *
+ * Kern E. Sibbald, MM
+ *
+ * Version $Id$
+ *
+ */
#include "bacula.h"
#include "stored.h"
"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"
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 */
/* 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;}
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2001-2007 Free Software Foundation Europe e.V.
+ Copyright (C) 2001-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.
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");
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;
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;
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-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.
"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"
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 */
/* 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;}
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2001-2007 Free Software Foundation Europe e.V.
+ Copyright (C) 2001-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.
"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"
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':
/* 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;}
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-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.
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;
"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"
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;
}
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-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.
/* 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
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;
mt_stat->mt_fileno >= 0;
}
-static char *modes[] = {
+static const char *modes[] = {
"CREATE_READ_WRITE",
"OPEN_READ_WRITE",
"OPEN_READ_ONLY",
};
-static char *mode_to_str(int mode)
+static const char *mode_to_str(int mode)
{
static char buf[100];
if (mode < 1 || mode > 4) {
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-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.
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 */
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 */
};
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-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.
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();
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)));
-/*
- *
- * dvd.c -- Routines specific to DVD devices (and
- * possibly other removable hard media).
- *
- * Nicolas Boichat, MMV
- *
- * Version $Id$
- */
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2005-2006 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.
(FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
Switzerland, email:ftf@fsfeurope.org.
*/
+/*
+ *
+ * dvd.c -- Routines specific to DVD devices (and
+ * possibly other removable hard media).
+ *
+ * Nicolas Boichat, MMV
+ *
+ * Version $Id$
+ */
#include "bacula.h"
#include "stored.h"
dcr->VolCatInfo.VolCatBytes = 0;
/* Update catalog */
- if (!dir_update_volume_info(dcr, false)) {
+ if (!dir_update_volume_info(dcr, false, true)) {
return false;
}
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-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.
/* 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";
{
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;
* 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
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);
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-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.
}
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) {
}
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);
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2002-2007 Free Software Foundation Europe e.V.
+ Copyright (C) 2002-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.
* 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;
* 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;
* 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");
}
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;
}
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"),
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);
}
/*
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 */
}
/*
/*
* 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));
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-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.
};
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);
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);
-/*
- *
- * record.c -- tape record handling functions
- *
- * Kern Sibbald, April MMI
- * added BB02 format October MMII
- *
- * Version $Id$
- *
- */
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2001-2006 Free Software Foundation Europe e.V.
+ Copyright (C) 2001-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.
(FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
Switzerland, email:ftf@fsfeurope.org.
*/
+/*
+ *
+ * record.c -- tape record handling functions
+ *
+ * Kern Sibbald, April MMI
+ * added BB02 format October MMII
+ *
+ * Version $Id$
+ *
+ */
#include "bacula.h"
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);
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);
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-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.
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);
}
}
* 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.
*
* 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);
+ unload_autochanger(dcr, -1); /* unload the volume */
+ free_volume(dev);
debug_list_volumes("reserve_vol free");
- vol_list->remove(vol);
- free_vol_item(vol);
}
}
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;
* 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 {
dlist *temp_vol_list, *save_vol_list;
VOLRES *vol = NULL;
lock_volumes();
+ Dmsg0(dbglvl, "lock volumes\n");
/*
* Create a temporary copy of the volume list. We do this,
*/
if (dcr->volume_in_use && !rctx.PreferMountedVols) {
rctx.PreferMountedVols = true;
+ if (dcr->VolumeName[0]) {
+ volume_unused(dcr);
+ }
+ goto bail_out;
+ }
+ /*
+ * Note. Under some circumstances, the Director can hand us
+ * a Volume name that is no the same as the one on the current
+ * drive, and in that case, the call above to find the next
+ * volume will fail because in attempting to reserve the Volume
+ * the code will realize that we already have a tape mounted,
+ * and it will fail. This *should* only happen if there are
+ * writers, thus the following test. In that case, we simply
+ * bail out, and continue waiting, rather than plunging on
+ * and hoping that the operator can resolve the problem.
+ */
+ if (dcr->dev->num_writers != 0) {
+ if (dcr->VolumeName[0]) {
+ volume_unused(dcr);
+ }
goto bail_out;
}
}
return ok;
}
+static int is_pool_ok(DCR *dcr)
+{
+ DEVICE *dev = dcr->dev;
+ JCR *jcr = dcr->jcr;
+
+ /* Now check if we want the same Pool and pool type */
+ if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
+ strcmp(dev->pool_type, dcr->pool_type) == 0) {
+ /* OK, compatible device */
+ Dmsg1(dbglvl, "OK dev: %s num_writers=0, reserved, pool matches\n", dev->print_name());
+ return 1;
+ } else {
+ /* Drive Pool not suitable for us */
+ Mmsg(jcr->errmsg, _(
+"3608 JobId=%u wants Pool=\"%s\" but have Pool=\"%s\" nreserve=%d on drive %s.\n"),
+ (uint32_t)jcr->JobId, dcr->pool_name, dev->pool_name,
+ dev->reserved_device, dev->print_name());
+ queue_reserve_message(jcr);
+ Dmsg2(dbglvl, "failed: busy num_writers=0, reserved, pool=%s wanted=%s\n",
+ dev->pool_name, dcr->pool_name);
+ }
+ return 0;
+}
+
+static bool is_max_jobs_ok(DCR *dcr)
+{
+ DEVICE *dev = dcr->dev;
+ JCR *jcr = dcr->jcr;
+
+ Dmsg4(dbglvl, "MaxJobs=%d Jobs=%d reserves=%d Vol=%s\n",
+ dcr->VolCatInfo.VolCatMaxJobs,
+ dcr->VolCatInfo.VolCatJobs, dev->reserved_device,
+ dcr->VolumeName);
+ if (dcr->VolCatInfo.VolCatMaxJobs > 0 && dcr->VolCatInfo.VolCatMaxJobs <=
+ (dcr->VolCatInfo.VolCatJobs + dev->reserved_device)) {
+ /* Max Job Vols depassed or already reserved */
+ Mmsg(jcr->errmsg, _("3610 JobId=%u Volume max jobs exceeded on drive %s.\n"),
+ (uint32_t)jcr->JobId, dev->print_name());
+ queue_reserve_message(jcr);
+ Dmsg1(dbglvl, "reserve dev failed: %s", jcr->errmsg);
+ return false; /* wait */
+ }
+ return true;
+}
+
/*
* Returns: 1 if drive can be reserved
* 0 if we should wait
rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
rctx.autochanger_only, rctx.any_drive);
+ /* Check for max jobs on this Volume */
+ if (!is_max_jobs_ok(dcr)) {
+ return 0;
+ }
+
/* setting any_drive overrides PreferMountedVols flag */
if (!rctx.any_drive) {
/*
if (dev->num_writers == 0) {
/* Now check if there are any reservations on the drive */
if (dev->reserved_device) {
- /* Now check if we want the same Pool and pool type */
- if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
- strcmp(dev->pool_type, dcr->pool_type) == 0) {
- /* OK, compatible device */
- Dmsg2(dbglvl, "jid=%u OK dev: %s num_writers=0, reserved, pool matches\n",
- jcr->JobId, dev->print_name());
- return 1;
- } else {
- /* Drive Pool not suitable for us */
- Mmsg(jcr->errmsg, _(
-"3608 JobId=%u wants Pool=\"%s\" but have Pool=\"%s\" nreserve=%d on drive %s.\n"),
- jcr->JobId, dcr->pool_name, dev->pool_name,
- dev->reserved_device, dev->print_name());
- queue_reserve_message(jcr);
- Dmsg3(dbglvl, "jid=%u failed: busy num_writers=0, reserved, pool=%s wanted=%s\n",
- (int)jcr->JobId, dev->pool_name, dcr->pool_name);
- return 0; /* wait */
- }
+ return is_pool_ok(dcr);
} else if (dev->can_append()) {
- /* Device in append mode, check if changing pool */
- if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
- strcmp(dev->pool_type, dcr->pool_type) == 0) {
- Dmsg2(dbglvl, "jid=%u OK dev: %s num_writers=0, can_append, pool matches.\n",
- jcr->JobId, dev->print_name());
- /* OK, compatible device */
- return 1;
+ if (is_pool_ok(dcr)) {
+ return 1;
} else {
/* Changing pool, unload old tape if any in drive */
Dmsg1(dbglvl, "jid=%u OK dev: num_writers=0, not reserved, pool change, unload changer\n",
* available if pool is the same).
*/
if (dev->can_append() || dev->num_writers > 0) {
- /* Yes, now check if we want the same Pool and pool type */
- if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
- strcmp(dev->pool_type, dcr->pool_type) == 0) {
- Dmsg2(dbglvl, "jid=%u OK dev: %s num_writers>=0, can_append, pool matches.\n",
- jcr->JobId, dev->print_name());
- /* OK, compatible device */
- return 1;
- } else {
- /* Drive Pool not suitable for us */
- Mmsg(jcr->errmsg, _("3609 JobId=%u wants Pool=\"%s\" but has Pool=\"%s\" on drive %s.\n"),
- jcr->JobId, dcr->pool_name, dev->pool_name, dev->print_name());
- queue_reserve_message(jcr);
- Dmsg3(dbglvl, "jid=%u failed: busy num_writers>0, can_append, pool=%s wanted=%s\n",
- (int)jcr->JobId, dev->pool_name, dcr->pool_name);
- return 0; /* wait */
- }
+ return is_pool_ok(dcr);
} else {
Pmsg1(000, _("Logic error!!!! JobId=%u Should not get here.\n"), (int)jcr->JobId);
Mmsg(jcr->errmsg, _("3910 JobId=%u Logic error!!!! drive %s Should not get here.\n"),
*/
#undef VERSION
-#define VERSION "2.2.7"
-#define BDATE "24 December 2007"
-#define LSMDATE "24Dec07"
+#define VERSION "2.2.8"
+#define BDATE "01 January 2008"
+#define LSMDATE "01Jan08"
-#define PROG_COPYRIGHT "Copyright (C) %d-2007 Free Software Foundation Europe e.V.\n"
-#define BYEAR "2007" /* year for copyright messages in progs */
+#define PROG_COPYRIGHT "Copyright (C) %d-2008 Free Software Foundation Europe e.V.\n"
+#define BYEAR "2008" /* year for copyright messages in progs */
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-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.
Technical notes on version 2.2
General:
+03Jan08
+kes Move Heartbeat documentation from Job to Director resource.
+ This fixes bug #1033.
+02Jan08
+kes Fix existing switch drive SD code to call autochanger to release
+ any old volume. This must be done to keep the autochanger from
+ releasing subsequently newly reserved volumes in doing a close().
+ This should fix bug #1018.
+kes Apply big backport of current SVN SD code that corrects a number
+ of race conditions. This is a first step in fixing bug #1018.
+29Dec07
+ebl Fixes bug #1028 where "Selection Type" option was not usable
+ with JobDefs.
+
+
+Release Version 2.2.7
24Dec07
kes Partial back out (disabled) %f job code editing because it
does not build on Win32.