2 This patch has a number of cleanups and improvements to the SD
3 reservations system. It should fix a number of problems with
4 dual drive autochangers as well ensure that volume use durations
5 and max volume jobs are better respected.
7 Apply it to version 2.2.7 (possibly some earlier versions) with:
10 patch -p1 <2.2.7-reserve.patch
11 ./configure <your options>
17 diff -ur k1/src/lib/message.c k3/src/lib/message.c
18 --- k1/src/lib/message.c 2007-10-19 13:47:58.000000000 +0200
19 +++ k3/src/lib/message.c 2007-12-22 19:13:00.000000000 +0100
21 int verbose = 0; /* increase User messages */
22 /* Keep debug level set to zero by default */
23 int debug_level = 0; /* debug level */
24 +bool dbg_timestamp = false; /* print timestamp in debug output */
25 time_t daemon_start_time = 0; /* Daemon start time */
26 const char *version = VERSION " (" BDATE ")";
27 char my_name[30]; /* daemon name is stored here */
28 diff -ur k1/src/lib/message.h k3/src/lib/message.h
29 --- k1/src/lib/message.h 2007-10-03 13:36:47.000000000 +0200
30 +++ k3/src/lib/message.h 2007-12-22 19:13:06.000000000 +0100
32 extern DLL_IMP_EXP sql_escape p_sql_escape;
34 extern DLL_IMP_EXP int debug_level;
35 +extern DLL_IMP_EXP bool dbg_timestamp; /* print timestamp in debug output */
36 extern DLL_IMP_EXP int verbose;
37 extern DLL_IMP_EXP char my_name[];
38 extern DLL_IMP_EXP const char * working_directory;
39 diff -ur k1/src/stored/acquire.c k3/src/stored/acquire.c
40 --- k1/src/stored/acquire.c 2007-09-14 11:49:06.000000000 +0200
41 +++ k3/src/stored/acquire.c 2007-12-22 19:12:23.000000000 +0100
44 * Kern Sibbald, August MMII
46 - * Version $Id: acquire.c 5552 2007-09-14 09:49:06Z kerns $
47 + * Version $Id: acquire.c 6081 2007-12-21 14:11:40Z kerns $
50 #include "bacula.h" /* pull in global headers */
53 /* Forward referenced functions */
54 static void attach_dcr_to_dev(DCR *dcr);
55 +static bool is_suitable_volume_mounted(DCR *dcr);
58 /*********************************************************************
61 DCR *acquire_device_for_append(DCR *dcr)
63 - bool release = false;
64 - bool recycle = false;
65 bool do_mount = false;
66 + bool release = false;
68 DEVICE *dev = dcr->dev;
76 + * have_vol defines whether or not mount_next_write_volume should
77 + * ask the Director again about what Volume to use.
79 + have_vol = is_suitable_volume_mounted(dcr);
80 if (dev->can_append()) {
81 Dmsg0(190, "device already in append.\n");
84 * dcr->VolumeName is what we pass into the routines, or
85 * get back from the subroutines.
87 - bstrncpy(dcr->VolumeName, dev->VolHdr.VolumeName, sizeof(dcr->VolumeName));
88 - if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE) &&
90 !(dir_find_next_appendable_volume(dcr) &&
91 strcmp(dev->VolHdr.VolumeName, dcr->VolumeName) == 0)) { /* wrong tape mounted */
92 - Dmsg2(190, "Wrong tape mounted: %s. wants:%s\n", dev->VolHdr.VolumeName,
94 - /* Release volume reserved by dir_find_next_appendable_volume() */
95 - if (dcr->VolumeName[0]) {
98 - if (dev->num_writers != 0) {
99 - Jmsg3(jcr, M_FATAL, 0, _("Wanted to append to Volume \"%s\", but device %s is busy writing on \"%s\" .\n"),
100 - dcr->VolumeName, dev->print_name(), dev->VolHdr.VolumeName);
101 - Dmsg3(200, "Wanted to append to Volume \"%s\", but device %s is busy writing on \"%s\" .\n",
102 - dcr->VolumeName, dev->print_name(), dev->VolHdr.VolumeName);
105 /* Wrong tape mounted, release it, then fall through to get correct one */
106 - Dmsg0(190, "Wrong tape mounted, release and try mount.\n");
107 + Dmsg0(50, "Wrong tape mounted, release and try mount.\n");
111 @@ -378,14 +370,17 @@
112 * we do not need to do mount_next_write_volume(), unless
113 * we need to recycle the tape.
115 - recycle = strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") == 0;
116 - Dmsg1(190, "Correct tape mounted. recycle=%d\n", recycle);
117 - if (recycle && dev->num_writers != 0) {
118 + do_mount = strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") == 0;
119 + Dmsg2(190, "jid=%u Correct tape mounted. recycle=%d\n",
120 + (uint32_t)jcr->JobId, do_mount);
122 + if (do_mount && dev->num_writers != 0) {
123 Jmsg(jcr, M_FATAL, 0, _("Cannot recycle volume \"%s\""
124 " on device %s because it is in use by another job.\n"),
125 dev->VolHdr.VolumeName, dev->print_name());
129 if (dev->num_writers == 0) {
130 memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
132 @@ -415,21 +410,23 @@
135 /* Not already in append mode, so mount the device */
136 - Dmsg0(190, "Not in append mode, try mount.\n");
137 + Dmsg2(190, "jid=%u Not in append mode, try mount have_vol=%d\n",
138 + (uint32_t)jcr->JobId, have_vol);
140 ASSERT(dev->num_writers == 0);
144 - if (do_mount || recycle) {
145 - Dmsg0(190, "Do mount_next_write_vol\n");
146 - bool mounted = mount_next_write_volume(dcr, release);
147 + if (do_mount || !have_vol) {
148 + Dmsg1(190, "jid=%u Do mount_next_write_vol\n", (uint32_t)jcr->JobId);
149 + bool mounted = mount_next_write_volume(dcr, have_vol, release);
151 if (!job_canceled(jcr)) {
152 /* Reduce "noise" -- don't print if job canceled */
153 Jmsg(jcr, M_FATAL, 0, _("Could not ready device %s for append.\n"),
155 - Dmsg1(200, "Could not ready device %s for append.\n",
156 - dev->print_name());
157 + Dmsg2(200, "jid=%u Could not ready device %s for append.\n",
158 + (uint32_t)jcr->JobId, dev->print_name());
162 @@ -441,11 +438,12 @@
163 jcr->NumWriteVolumes = 1;
165 dev->VolCatInfo.VolCatJobs++; /* increment number of jobs on vol */
166 - dir_update_volume_info(dcr, false); /* send Volume info to Director */
167 + dir_update_volume_info(dcr, false, false); /* send Volume info to Director */
169 if (dcr->reserved_device) {
170 dev->reserved_device--;
171 - Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
172 + Dmsg3(100, "jid=%u Dec reserve=%d dev=%s\n", (uint32_t)jcr->JobId,
173 + dev->reserved_device, dev->print_name());
174 dcr->reserved_device = false;
176 dev->dunblock(DEV_LOCKED);
179 if (dcr->reserved_device) {
180 dev->reserved_device--;
181 - Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
182 + Dmsg3(100, "jid=%u Dec reserve=%d dev=%s\n", (uint32_t)jcr->JobId,
183 + dev->reserved_device, dev->print_name());
184 dcr->reserved_device = false;
186 dev->dunblock(DEV_LOCKED);
191 +static bool is_suitable_volume_mounted(DCR *dcr)
193 + DEVICE *dev = dcr->dev;
195 + /* Volume mounted? */
196 + if (dev->VolHdr.VolumeName[0] == 0) {
197 + return false; /* no */
199 + bstrncpy(dcr->VolumeName, dev->VolHdr.VolumeName, sizeof(dcr->VolumeName));
200 + return dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE);
204 * This job is done, so release the device. From a Unix standpoint,
205 * the device remains open.
207 if (dev->can_read()) {
208 dev->clear_read(); /* clear read bit */
209 Dmsg0(100, "dir_update_vol_info. Release0\n");
210 - dir_update_volume_info(dcr, false); /* send Volume info to Director */
211 + dir_update_volume_info(dcr, false, false); /* send Volume info to Director */
213 } else if (dev->num_writers > 0) {
216 dev->VolCatInfo.VolCatFiles = dev->file; /* set number of files */
217 /* Note! do volume update before close, which zaps VolCatInfo */
218 Dmsg0(100, "dir_update_vol_info. Release0\n");
219 - dir_update_volume_info(dcr, false); /* send Volume info to Director */
220 + dir_update_volume_info(dcr, false, false); /* send Volume info to Director */
225 if (dcr->attached_to_dev) {
226 detach_dcr_from_dev(dcr);
228 - dcr->max_job_spool_size = dev->device->max_job_spool_size;
229 + /* Use job spoolsize prior to device spoolsize */
230 + if (jcr->spool_size) {
231 + dcr->max_job_spool_size = jcr->spool_size;
233 + dcr->max_job_spool_size = dev->device->max_job_spool_size;
235 dcr->device = dev->device;
237 attach_dcr_to_dev(dcr);
238 diff -ur k1/src/stored/askdir.c k3/src/stored/askdir.c
239 --- k1/src/stored/askdir.c 2007-09-09 12:03:23.000000000 +0200
240 +++ k3/src/stored/askdir.c 2007-12-22 19:11:50.000000000 +0100
243 * Kern Sibbald, December 2000
245 - * Version $Id: askdir.c 5503 2007-09-09 10:03:23Z kerns $
246 + * Version $Id: askdir.c 5852 2007-11-04 19:57:42Z kerns $
249 #include "bacula.h" /* pull in global headers */
251 static char Get_Vol_Info[] = "CatReq Job=%s GetVolInfo VolName=%s write=%d\n";
252 static char Update_media[] = "CatReq Job=%s UpdateMedia VolName=%s"
253 " VolJobs=%u VolFiles=%u VolBlocks=%u VolBytes=%s VolMounts=%u"
254 - " VolErrors=%u VolWrites=%u MaxVolBytes=%s EndTime=%d VolStatus=%s"
255 + " VolErrors=%u VolWrites=%u MaxVolBytes=%s EndTime=%s VolStatus=%s"
256 " Slot=%d relabel=%d InChanger=%d VolReadTime=%s VolWriteTime=%s"
257 " VolFirstWritten=%s VolParts=%u\n";
258 static char Create_job_media[] = "CatReq Job=%s CreateJobMedia"
261 pm_strcpy(ChangerName, "*");
263 - ok =bnet_fsend(dir, Device_update,
264 + ok = dir->fsend(Device_update,
267 dev->can_append()!=0,
269 pm_strcpy(MediaType, device->media_type);
270 bash_spaces(MediaType);
271 /* This is mostly to indicate that we are here */
272 - ok = bnet_fsend(dir, Device_update,
273 + ok = dir->fsend(Device_update,
275 dev_name.c_str(), /* Changer name */
276 0, 0, 0, /* append, read, num_writers */
279 bool dir_send_job_status(JCR *jcr)
281 - return bnet_fsend(jcr->dir_bsock, Job_status, jcr->Job, jcr->JobStatus);
282 + return jcr->dir_bsock->fsend(Job_status, jcr->Job, jcr->JobStatus);
289 memset(&vol, 0, sizeof(vol));
290 - Dmsg1(100, "<dird %s\n", dir->msg);
291 + Dmsg1(100, "<dird %s", dir->msg);
292 n = sscanf(dir->msg, OK_media, vol.VolCatName,
293 &vol.VolCatJobs, &vol.VolCatFiles,
294 &vol.VolCatBlocks, &vol.VolCatBytes,
296 &vol.EndFile, &vol.EndBlock, &vol.VolCatParts,
297 &vol.LabelType, &vol.VolMediaId);
299 - Dmsg3(100, "Bad response from Dir fields=%d, len=%d: %s", n, dir->msglen, dir->msg);
300 + Dmsg3(100, "Bad response from Dir fields=%d, len=%d: %s",
301 + n, dir->msglen, dir->msg);
302 Mmsg(jcr->errmsg, _("Error getting Volume info: %s"), dir->msg);
306 bash_spaces(dcr->VolCatInfo.VolCatName);
307 dir->fsend(Get_Vol_Info, jcr->Job, dcr->VolCatInfo.VolCatName,
308 writing==GET_VOL_INFO_FOR_WRITE?1:0);
309 - Dmsg1(100, ">dird: %s\n", dir->msg);
310 + Dmsg1(100, ">dird %s", dir->msg);
311 unbash_spaces(dcr->VolCatInfo.VolCatName);
312 bool ok = do_get_volume_info(dcr);
315 BSOCK *dir = jcr->dir_bsock;
318 - Dmsg0(200, "dir_find_next_appendable_volume\n");
319 + Dmsg2(200, "dir_find_next_appendable_volume: reserved=%d Vol=%s\n",
320 + dcr->reserved_device, dcr->VolumeName);
323 * Try the twenty oldest or most available volumes. Note,
324 * the most available could already be mounted on another
326 dir->fsend(Find_media, jcr->Job, vol_index, dcr->pool_name, dcr->media_type);
327 unbash_spaces(dcr->media_type);
328 unbash_spaces(dcr->pool_name);
329 - Dmsg1(100, ">dird: %s", dir->msg);
330 + Dmsg1(100, ">dird %s", dir->msg);
331 bool ok = do_get_volume_info(dcr);
333 if (!is_volume_in_use(dcr)) {
334 @@ -311,14 +314,13 @@
335 * back to the director. The information comes from the
338 -bool dir_update_volume_info(DCR *dcr, bool label)
339 +bool dir_update_volume_info(DCR *dcr, bool label, bool update_LastWritten)
342 BSOCK *dir = jcr->dir_bsock;
343 DEVICE *dev = dcr->dev;
344 - time_t LastWritten = time(NULL);
345 VOLUME_CAT_INFO *vol = &dev->VolCatInfo;
346 - char ed1[50], ed2[50], ed3[50], ed4[50], ed5[50];
347 + char ed1[50], ed2[50], ed3[50], ed4[50], ed5[50], ed6[50];
351 @@ -341,21 +343,25 @@
353 bstrncpy(vol->VolCatStatus, "Append", sizeof(vol->VolCatStatus));
355 +// if (update_LastWritten) {
356 + vol->VolLastWritten = time(NULL);
358 pm_strcpy(VolumeName, vol->VolCatName);
359 bash_spaces(VolumeName);
360 InChanger = vol->InChanger;
361 - bnet_fsend(dir, Update_media, jcr->Job,
362 + dir->fsend(Update_media, jcr->Job,
363 VolumeName.c_str(), vol->VolCatJobs, vol->VolCatFiles,
364 vol->VolCatBlocks, edit_uint64(vol->VolCatBytes, ed1),
365 vol->VolCatMounts, vol->VolCatErrors,
366 vol->VolCatWrites, edit_uint64(vol->VolCatMaxBytes, ed2),
367 - LastWritten, vol->VolCatStatus, vol->Slot, label,
368 + edit_uint64(vol->VolLastWritten, ed6),
369 + vol->VolCatStatus, vol->Slot, label,
370 InChanger, /* bool in structure */
371 edit_int64(vol->VolReadTime, ed3),
372 edit_int64(vol->VolWriteTime, ed4),
373 edit_uint64(vol->VolFirstWritten, ed5),
375 - Dmsg1(100, ">dird: %s", dir->msg);
376 + Dmsg1(100, ">dird %s", dir->msg);
378 /* Do not lock device here because it may be locked from label */
379 if (!do_get_volume_info(dcr)) {
381 vol->VolCatName, jcr->errmsg);
384 - Dmsg1(420, "get_volume_info(): %s", dir->msg);
385 + Dmsg1(420, "get_volume_info() %s", dir->msg);
386 /* Update dev Volume info in case something changed (e.g. expired) */
387 dev->VolCatInfo = dcr->VolCatInfo;
389 @@ -393,20 +399,20 @@
392 dcr->WroteVol = false;
393 - bnet_fsend(dir, Create_job_media, jcr->Job,
394 + dir->fsend(Create_job_media, jcr->Job,
395 dcr->VolFirstIndex, dcr->VolLastIndex,
396 dcr->StartFile, dcr->EndFile,
397 dcr->StartBlock, dcr->EndBlock,
398 dcr->Copy, dcr->Stripe,
399 edit_uint64(dcr->VolMediaId, ed1));
400 - Dmsg1(100, ">dird: %s", dir->msg);
401 + Dmsg1(100, ">dird %s", dir->msg);
402 if (bnet_recv(dir) <= 0) {
403 Dmsg0(190, "create_jobmedia error bnet_recv\n");
404 Jmsg(jcr, M_FATAL, 0, _("Error creating JobMedia record: ERR=%s\n"),
405 - bnet_strerror(dir));
409 - Dmsg1(100, "<dir: %s", dir->msg);
410 + Dmsg1(100, "<dird %s", dir->msg);
411 if (strcmp(dir->msg, OK_create) != 0) {
412 Dmsg1(130, "Bad response from Dir: %s\n", dir->msg);
413 Jmsg(jcr, M_FATAL, 0, _("Error creating JobMedia record: %s\n"), dir->msg);
418 - dir->msglen = sprintf(dir->msg, FileAttributes, jcr->Job);
419 - dir->msg = check_pool_memory_size(dir->msg, dir->msglen +
420 - sizeof(DEV_RECORD) + rec->data_len);
421 + dir->msg = check_pool_memory_size(dir->msg, sizeof(FileAttributes) +
422 + MAX_NAME_LENGTH + sizeof(DEV_RECORD) + rec->data_len + 1);
423 + dir->msglen = bsnprintf(dir->msg, sizeof(FileAttributes) +
424 + MAX_NAME_LENGTH + 1, FileAttributes, jcr->Job);
425 ser_begin(dir->msg + dir->msglen, 0);
426 ser_uint32(rec->VolSessionId);
427 ser_uint32(rec->VolSessionTime);
429 ser_uint32(rec->data_len);
430 ser_bytes(rec->data, rec->data_len);
431 dir->msglen = ser_length(dir->msg);
432 - Dmsg1(1800, ">dird: %s\n", dir->msg); /* Attributes */
433 - return bnet_send(dir);
434 + Dmsg1(1800, ">dird %s\n", dir->msg); /* Attributes */
435 + return dir->send();
439 diff -ur k1/src/stored/bcopy.c k3/src/stored/bcopy.c
440 --- k1/src/stored/bcopy.c 2007-12-03 20:27:38.000000000 +0100
441 +++ k3/src/stored/bcopy.c 2007-12-22 19:10:29.000000000 +0100
443 * Kern E. Sibbald, October 2002
446 - * Version $Id: bcopy.c 6017 2007-12-03 19:27:38Z kerns $
447 + * Version $Id: bcopy.c 6016 2007-12-03 19:27:21Z kerns $
452 int generate_daemon_event(JCR *jcr, const char *event) { return 1; }
454 /* Forward referenced functions */
455 +static void get_session_record(DEVICE *dev, DEV_RECORD *rec, SESSION_LABEL *sessrec);
456 static bool record_cb(DCR *dcr, DEV_RECORD *rec);
460 static JCR *out_jcr; /* output jcr */
461 static BSR *bsr = NULL;
462 static const char *wd = "/tmp";
463 -static int list_records = 0;
464 +static bool list_records = false;
465 static uint32_t records = 0;
466 static uint32_t jobs = 0;
467 static DEV_BLOCK *out_block;
468 +static SESSION_LABEL sessrec;
470 #define CONFIG_FILE "bacula-sd.conf"
471 char *configfile = NULL;
473 "Usage: bcopy [-d debug_level] <input-archive> <output-archive>\n"
474 " -b bootstrap specify a bootstrap file\n"
475 " -c <file> specify configuration file\n"
476 -" -d <nn> set debug level to nn\n"
477 +" -d <nn> set debug level to <nn>\n"
478 " -i specify input Volume names (separated by |)\n"
479 " -o specify output Volume names (separated by |)\n"
480 " -p proceed inspite of errors\n"
484 case 'd': /* debug level */
485 - debug_level = atoi(optarg);
486 - if (debug_level <= 0)
488 + if (*optarg == 't') {
489 + dbg_timestamp = true;
491 + debug_level = atoi(optarg);
492 + if (debug_level <= 0) {
498 case 'i': /* input Volume name */
500 out_block = out_jcr->dcr->block;
502 ok = read_records(in_jcr->dcr, record_cb, mount_next_read_volume);
504 if (ok || out_dev->can_write()) {
505 if (!write_block_to_device(out_jcr->dcr)) {
506 Pmsg0(000, _("Write of last block failed.\n"));
510 if (rec->FileIndex < 0) {
511 + get_session_record(in_dcr->dev, rec, &sessrec);
514 dump_label_record(in_dcr->dev, rec, 1);
515 @@ -294,10 +303,46 @@
519 +static void get_session_record(DEVICE *dev, DEV_RECORD *rec, SESSION_LABEL *sessrec)
522 + memset(sessrec, 0, sizeof(sessrec));
523 + switch (rec->FileIndex) {
525 + rtype = _("Fresh Volume Label");
528 + rtype = _("Volume Label");
529 + unser_volume_label(dev, rec);
532 + rtype = _("Begin Job Session");
533 + unser_session_label(sessrec, rec);
536 + rtype = _("End Job Session");
537 + unser_session_label(sessrec, rec);
541 + rtype = _("End of Medium");
544 + rtype = _("Unknown");
547 + Dmsg5(10, "%s Record: VolSessionId=%d VolSessionTime=%d JobId=%d DataLen=%d\n",
548 + rtype, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len);
550 + Pmsg5(-1, _("%s Record: VolSessionId=%d VolSessionTime=%d JobId=%d DataLen=%d\n"),
551 + rtype, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len);
556 /* Dummies to replace askdir.c */
557 bool dir_find_next_appendable_volume(DCR *dcr) { return 1;}
558 -bool dir_update_volume_info(DCR *dcr, bool relabel) { return 1; }
559 +bool dir_update_volume_info(DCR *dcr, bool relabel, bool update_LastWritten) { return 1; }
560 bool dir_create_jobmedia_record(DCR *dcr) { return 1; }
561 bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr) { return 1; }
562 bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec) { return 1;}
563 diff -ur k1/src/stored/bextract.c k3/src/stored/bextract.c
564 --- k1/src/stored/bextract.c 2007-10-03 13:36:47.000000000 +0200
565 +++ k3/src/stored/bextract.c 2007-12-22 19:10:20.000000000 +0100
568 * Kern E. Sibbald, MM
570 - * Version $Id: bextract.c 5713 2007-10-03 11:36:47Z kerns $
571 + * Version $Id: bextract.c 5852 2007-11-04 19:57:42Z kerns $
576 "Usage: bextract <options> <bacula-archive-device-name> <directory-to-store-files>\n"
577 " -b <file> specify a bootstrap file\n"
578 " -c <file> specify a configuration file\n"
579 -" -d <nn> set debug level to nn\n"
580 +" -d <nn> set debug level to <nn>\n"
581 " -e <file> exclude list\n"
582 " -i <file> include list\n"
583 " -p proceed inspite of I/O errors\n"
587 case 'd': /* debug level */
588 - debug_level = atoi(optarg);
589 - if (debug_level <= 0)
591 + if (*optarg == 't') {
592 + dbg_timestamp = true;
594 + debug_level = atoi(optarg);
595 + if (debug_level <= 0) {
601 case 'e': /* exclude list */
604 /* Dummies to replace askdir.c */
605 bool dir_find_next_appendable_volume(DCR *dcr) { return 1;}
606 -bool dir_update_volume_info(DCR *dcr, bool relabel) { return 1; }
607 +bool dir_update_volume_info(DCR *dcr, bool relabel, bool update_LastWritten) { return 1; }
608 bool dir_create_jobmedia_record(DCR *dcr) { return 1; }
609 bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr) { return 1; }
610 bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec) { return 1;}
611 diff -ur k1/src/stored/block.c k3/src/stored/block.c
612 --- k1/src/stored/block.c 2007-10-03 13:36:47.000000000 +0200
613 +++ k3/src/stored/block.c 2007-12-22 19:12:33.000000000 +0100
615 * Kern Sibbald, March MMI
616 * added BB02 format October MMII
618 - * Version $Id: block.c 5713 2007-10-03 11:36:47Z kerns $
619 + * Version $Id: block.c 5852 2007-11-04 19:57:42Z kerns $
624 dev->VolCatInfo.VolCatParts = dev->num_dvd_parts;
627 - if (!dir_update_volume_info(dcr, false)) {
628 + if (!dir_update_volume_info(dcr, false, true)) {
631 Dmsg1(100, "dir_update_volume_info terminate writing -- %s\n", ok?"OK":"ERROR");
635 dev->VolCatInfo.VolCatFiles = dev->file;
636 - if (!dir_update_volume_info(dcr, false)) {
637 + if (!dir_update_volume_info(dcr, false, false)) {
638 Dmsg0(190, "Error from update_vol_info.\n");
639 terminate_writing_volume(dcr);
640 dev->dev_errno = EIO;
643 dev->VolCatInfo.VolCatParts = dev->num_dvd_parts;
645 - if (!dir_update_volume_info(dcr, false)) {
646 + if (!dir_update_volume_info(dcr, false, false)) {
647 Dmsg0(190, "Error from update_vol_info.\n");
648 dev->dev_errno = EIO;
650 diff -ur k1/src/stored/bls.c k3/src/stored/bls.c
651 --- k1/src/stored/bls.c 2007-10-03 13:36:47.000000000 +0200
652 +++ k3/src/stored/bls.c 2007-12-22 19:10:57.000000000 +0100
657 - * Version $Id: bls.c 5713 2007-10-03 11:36:47Z kerns $
658 + * Version $Id: bls.c 5852 2007-11-04 19:57:42Z kerns $
663 "Usage: bls [options] <device-name>\n"
664 " -b <file> specify a bootstrap file\n"
665 " -c <file> specify a config file\n"
666 -" -d <level> specify debug level\n"
667 +" -d <nn> set debug level to <nn>\n"
668 " -e <file> exclude list\n"
669 " -i <file> include list\n"
674 case 'd': /* debug level */
675 - debug_level = atoi(optarg);
676 - if (debug_level <= 0)
678 + if (*optarg == 't') {
679 + dbg_timestamp = true;
681 + debug_level = atoi(optarg);
682 + if (debug_level <= 0) {
688 case 'e': /* exclude list */
691 /* Dummies to replace askdir.c */
692 bool dir_find_next_appendable_volume(DCR *dcr) { return 1;}
693 -bool dir_update_volume_info(DCR *dcr, bool relabel) { return 1; }
694 +bool dir_update_volume_info(DCR *dcr, bool relabel, bool update_LastWritten) { return 1; }
695 bool dir_create_jobmedia_record(DCR *dcr) { return 1; }
696 bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr) { return 1; }
697 bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec) { return 1;}
698 diff -ur k1/src/stored/bscan.c k3/src/stored/bscan.c
699 --- k1/src/stored/bscan.c 2007-10-03 13:36:47.000000000 +0200
700 +++ k3/src/stored/bscan.c 2007-12-22 19:11:05.000000000 +0100
702 * Kern E. Sibbald, December 2001
705 - * Version $Id: bscan.c 5713 2007-10-03 11:36:47Z kerns $
706 + * Version $Id: bscan.c 5852 2007-11-04 19:57:42Z kerns $
711 "Usage: bscan [ options ] <bacula-archive>\n"
712 " -b bootstrap specify a bootstrap file\n"
713 " -c <file> specify configuration file\n"
714 -" -d <nn> set debug level to nn\n"
715 +" -d <nn> set debug level to <nn>\n"
716 " -m update media info in database\n"
717 " -n <name> specify the database name (default bacula)\n"
718 " -u <user> specify database user name (default bacula)\n"
722 case 'd': /* debug level */
723 - debug_level = atoi(optarg);
724 - if (debug_level <= 0)
726 + if (*optarg == 't') {
727 + dbg_timestamp = true;
729 + debug_level = atoi(optarg);
730 + if (debug_level <= 0) {
737 @@ -1271,7 +1276,7 @@
739 /* Dummies to replace askdir.c */
740 bool dir_find_next_appendable_volume(DCR *dcr) { return 1;}
741 -bool dir_update_volume_info(DCR *dcr, bool relabel) { return 1; }
742 +bool dir_update_volume_info(DCR *dcr, bool relabel, bool update_LastWritten) { return 1; }
743 bool dir_create_jobmedia_record(DCR *dcr) { return 1; }
744 bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr) { return 1; }
745 bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec) { return 1;}
746 diff -ur k1/src/stored/btape.c k3/src/stored/btape.c
747 --- k1/src/stored/btape.c 2007-06-07 16:46:43.000000000 +0200
748 +++ k3/src/stored/btape.c 2007-12-22 19:11:14.000000000 +0100
750 * Note, this program reads stored.conf, and will only
751 * talk to devices that are configured.
753 - * Version $Id: btape.c 4992 2007-06-07 14:46:43Z kerns $
754 + * Version $Id: btape.c 5852 2007-11-04 19:57:42Z kerns $
761 case 'd': /* set debug level */
762 - debug_level = atoi(optarg);
763 - if (debug_level <= 0) {
765 + if (*optarg == 't') {
766 + dbg_timestamp = true;
768 + debug_level = atoi(optarg);
769 + if (debug_level <= 0) {
775 @@ -2598,7 +2602,7 @@
776 "Usage: btape <options> <device_name>\n"
777 " -b <file> specify bootstrap file\n"
778 " -c <file> set configuration file to file\n"
779 -" -d <nn> set debug level to nn\n"
780 +" -d <nn> set debug level to <nn>\n"
781 " -p proceed inspite of I/O errors\n"
782 " -s turn off signals\n"
784 @@ -2644,7 +2648,7 @@
785 bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec) { return 1;}
786 bool dir_send_job_status(JCR *jcr) {return 1;}
788 -bool dir_update_volume_info(DCR *dcr, bool relabel)
789 +bool dir_update_volume_info(DCR *dcr, bool relabel, bool update_LastWritten)
793 diff -ur k1/src/stored/dev.c k3/src/stored/dev.c
794 --- k1/src/stored/dev.c 2007-12-02 19:03:17.000000000 +0100
795 +++ k3/src/stored/dev.c 2007-12-22 19:11:57.000000000 +0100
797 * daemon. More complicated coding (double buffering, writer
798 * thread, ...) is left for a later version.
800 - * Version $Id: dev.c 6011 2007-12-02 18:03:17Z kerns $
801 + * Version $Id: dev.c 5999 2007-11-29 21:36:36Z ricozz $
806 /* Forward referenced functions */
807 void set_os_device_parameters(DCR *dcr);
808 static bool dev_get_os_pos(DEVICE *dev, struct mtget *mt_stat);
809 -static char *mode_to_str(int mode);
810 +static const char *mode_to_str(int mode);
813 * Allocate and initialize the DEVICE structure
815 Mmsg2(errmsg, _("Could not open: %s, ERR=%s\n"), archive_name.c_str(),
817 Dmsg1(100, "open failed: %s", errmsg);
818 - Emsg0(M_FATAL, 0, errmsg);
819 + Jmsg1(NULL, M_WARNING, 0, "%s", errmsg);
823 @@ -2468,7 +2468,7 @@
824 mt_stat->mt_fileno >= 0;
827 -static char *modes[] = {
828 +static const char *modes[] = {
832 @@ -2476,7 +2476,7 @@
836 -static char *mode_to_str(int mode)
837 +static const char *mode_to_str(int mode)
839 static char buf[100];
840 if (mode < 1 || mode > 4) {
841 diff -ur k1/src/stored/dev.h k3/src/stored/dev.h
842 --- k1/src/stored/dev.h 2007-09-09 12:03:23.000000000 +0200
843 +++ k3/src/stored/dev.h 2007-12-22 19:12:14.000000000 +0100
848 - * Version $Id: dev.h 5503 2007-09-09 10:03:23Z kerns $
849 + * Version $Id: dev.h 5852 2007-11-04 19:57:42Z kerns $
854 btime_t VolWriteTime; /* time spent writing this Volume */
855 int64_t VolMediaId; /* MediaId */
856 utime_t VolFirstWritten; /* Time of first write */
857 + utime_t VolLastWritten; /* Time of last write */
858 bool InChanger; /* Set if vol in current magazine */
859 char VolCatStatus[20]; /* Volume status */
860 char VolCatName[MAX_NAME_LENGTH]; /* Desired volume to mount */
867 + char *vol_name; /* Volume name */
868 + DEVICE *dev; /* Pointer to device to which we are attached */
869 + bool released; /* set when the Volume can be released */
873 diff -ur k1/src/stored/device.c k3/src/stored/device.c
874 --- k1/src/stored/device.c 2007-06-29 14:12:26.000000000 +0200
875 +++ k3/src/stored/device.c 2007-12-22 19:11:23.000000000 +0100
878 * Kern Sibbald, MM, MMI
880 - * Version $Id: device.c 5114 2007-06-29 12:12:26Z kerns $
881 + * Version $Id: device.c 5852 2007-11-04 19:57:42Z kerns $
884 #include "bacula.h" /* pull in global headers */
886 edit_uint64_with_commas(dev->VolCatInfo.VolCatBlocks, b2),
887 bstrftime(dt, sizeof(dt), time(NULL)));
889 - if (!mount_next_write_volume(dcr, 1)) {
890 + /* Called with have_vol=false, release=true */
891 + if (!mount_next_write_volume(dcr, false, true)) {
892 free_block(label_blk);
896 dev->dlock(); /* lock again */
898 dev->VolCatInfo.VolCatJobs++; /* increment number of jobs on vol */
899 - dir_update_volume_info(dcr, false); /* send Volume info to Director */
900 + dir_update_volume_info(dcr, false, false); /* send Volume info to Director */
902 Jmsg(jcr, M_INFO, 0, _("New volume \"%s\" mounted on device %s at %s.\n"),
903 dcr->VolumeName, dev->print_name(), bstrftime(dt, sizeof(dt), time(NULL)));
904 diff -ur k1/src/stored/dvd.c k3/src/stored/dvd.c
905 --- k1/src/stored/dvd.c 2007-06-07 16:46:43.000000000 +0200
906 +++ k3/src/stored/dvd.c 2007-12-22 19:26:23.000000000 +0100
910 - * dvd.c -- Routines specific to DVD devices (and
911 - * possibly other removable hard media).
913 - * Nicolas Boichat, MMV
915 - * Version $Id: dvd.c 4992 2007-06-07 14:46:43Z kerns $
918 Bacula® - The Network Backup Solution
920 - Copyright (C) 2005-2006 Free Software Foundation Europe e.V.
921 + Copyright (C) 2005-2007 Free Software Foundation Europe e.V.
923 The main author of Bacula is Kern Sibbald, with contributions from
924 many others, a complete list can be found in the file AUTHORS.
926 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
927 Switzerland, email:ftf@fsfeurope.org.
931 + * dvd.c -- Routines specific to DVD devices (and
932 + * possibly other removable hard media).
934 + * Nicolas Boichat, MMV
936 + * Version $Id: dvd.c 5852 2007-11-04 19:57:42Z kerns $
942 dcr->VolCatInfo.VolCatBytes = 0;
945 - if (!dir_update_volume_info(dcr, false)) {
946 + if (!dir_update_volume_info(dcr, false, true)) {
950 diff -ur k1/src/stored/job.c k3/src/stored/job.c
951 --- k1/src/stored/job.c 2007-09-29 00:01:16.000000000 +0200
952 +++ k3/src/stored/job.c 2007-12-22 19:11:41.000000000 +0100
957 - * Version $Id: job.c 5686 2007-09-28 22:01:16Z kerns $
958 + * Version $Id: job.c 5697 2007-09-30 17:40:08Z ricozz $
963 /* Requests from the Director daemon */
964 static char jobcmd[] = "JobId=%d job=%127s job_name=%127s client_name=%127s "
965 "type=%d level=%d FileSet=%127s NoAttr=%d SpoolAttr=%d FileSetMD5=%127s "
966 + "SpoolData=%d WritePartAfterJob=%d PreferMountedVols=%d SpoolSize=%s\n";
967 +static char oldjobcmd[] = "JobId=%d job=%127s job_name=%127s client_name=%127s "
968 + "type=%d level=%d FileSet=%127s NoAttr=%d SpoolAttr=%d FileSetMD5=%127s "
969 "SpoolData=%d WritePartAfterJob=%d PreferMountedVols=%d\n";
973 /* Responses sent to Director daemon */
974 static char OKjob[] = "3000 OK Job SDid=%u SDtime=%u Authorization=%s\n";
975 static char BAD_job[] = "3915 Bad Job command. stat=%d CMD: %s\n";
980 + char spool_size[30];
982 BSOCK *dir = jcr->dir_bsock;
983 POOL_MEM job_name, client_name, job, fileset_name, fileset_md5;
985 * Get JobId and permissions from Director
987 Dmsg1(100, "<dird: %s", dir->msg);
988 + bstrncpy(spool_size, "0", sizeof(spool_size));
989 stat = sscanf(dir->msg, jobcmd, &JobId, job.c_str(), job_name.c_str(),
991 &JobType, &level, fileset_name.c_str(), &no_attributes,
992 - &spool_attributes, fileset_md5.c_str(), &spool_data,
993 + &spool_attributes, fileset_md5.c_str(), &spool_data,
994 + &write_part_after_job, &PreferMountedVols, spool_size);
996 + /* Try old version */
997 + stat = sscanf(dir->msg, oldjobcmd, &JobId, job.c_str(), job_name.c_str(),
998 + client_name.c_str(),
999 + &JobType, &level, fileset_name.c_str(), &no_attributes,
1000 + &spool_attributes, fileset_md5.c_str(), &spool_data,
1001 &write_part_after_job, &PreferMountedVols);
1003 - pm_strcpy(jcr->errmsg, dir->msg);
1004 - dir->fsend(BAD_job, stat, jcr->errmsg);
1005 - Dmsg1(100, ">dird: %s", dir->msg);
1006 - set_jcr_job_status(jcr, JS_ErrorTerminated);
1009 + pm_strcpy(jcr->errmsg, dir->msg);
1010 + dir->fsend(BAD_job, stat, jcr->errmsg);
1011 + Dmsg1(100, ">dird: %s", dir->msg);
1012 + set_jcr_job_status(jcr, JS_ErrorTerminated);
1017 * Since this job could be rescheduled, we
1019 jcr->no_attributes = no_attributes;
1020 jcr->spool_attributes = spool_attributes;
1021 jcr->spool_data = spool_data;
1022 + jcr->spool_size = str_to_int64(spool_size);
1023 jcr->write_part_after_job = write_part_after_job;
1024 jcr->fileset_md5 = get_pool_memory(PM_NAME);
1025 pm_strcpy(jcr->fileset_md5, fileset_md5);
1026 diff -ur k1/src/stored/label.c k3/src/stored/label.c
1027 --- k1/src/stored/label.c 2007-10-03 13:36:47.000000000 +0200
1028 +++ k3/src/stored/label.c 2007-12-22 19:10:49.000000000 +0100
1033 - * Version $Id: label.c 5713 2007-10-03 11:36:47Z kerns $
1034 + * Version $Id: label.c 5852 2007-11-04 19:57:42Z kerns $
1037 #include "bacula.h" /* pull in global headers */
1040 Dmsg0(150, "dir_update_vol_info. Set Append\n");
1041 bstrncpy(dev->VolCatInfo.VolCatStatus, "Append", sizeof(dev->VolCatInfo.VolCatStatus));
1042 - if (!dir_update_volume_info(dcr, true)) { /* indicate doing relabel */
1043 + if (!dir_update_volume_info(dcr, true, true)) { /* indicate doing relabel */
1051 - Jmsg1(jcr, M_ABORT, 0, _("Bad session label = %d\n"), label);
1052 + Jmsg1(jcr, M_ABORT, 0, _("Bad Volume session label = %d\n"), label);
1055 create_session_label(dcr, rec, label);
1056 diff -ur k1/src/stored/mount.c k3/src/stored/mount.c
1057 --- k1/src/stored/mount.c 2007-09-14 11:49:06.000000000 +0200
1058 +++ k3/src/stored/mount.c 2007-12-22 19:11:30.000000000 +0100
1061 * Kern Sibbald, August MMII
1063 - * Version $Id: mount.c 5552 2007-09-14 09:49:06Z kerns $
1064 + * Version $Id: mount.c 5852 2007-11-04 19:57:42Z kerns $
1067 #include "bacula.h" /* pull in global headers */
1069 * impossible to get the requested Volume.
1072 -bool mount_next_write_volume(DCR *dcr, bool release)
1073 +bool mount_next_write_volume(DCR *dcr, bool have_vol, bool release)
1076 bool ask = false, recycle, autochanger;
1077 @@ -108,12 +108,16 @@
1078 * in dcr->VolCatInfo
1080 Dmsg0(200, "Before dir_find_next_appendable_volume.\n");
1081 - while (!dir_find_next_appendable_volume(dcr)) {
1082 - Dmsg0(200, "not dir_find_next\n");
1083 - if (!dir_ask_sysop_to_create_appendable_volume(dcr)) {
1086 + while (!dir_find_next_appendable_volume(dcr)) {
1087 + Dmsg0(200, "not dir_find_next\n");
1088 + if (!dir_ask_sysop_to_create_appendable_volume(dcr)) {
1091 + Dmsg0(200, "Again dir_find_next_append...\n");
1093 - Dmsg0(200, "Again dir_find_next_append...\n");
1095 + have_vol = false; /* set false for next pass if any */
1097 if (job_canceled(jcr)) {
1100 * If we autochanged to correct Volume or (we have not just
1101 * released the Volume AND we can automount) we go ahead
1102 * and read the label. If there is no tape in the drive,
1103 - * we will err, recurse and ask the operator the next time.
1104 + * we will fail, recurse and ask the operator the next time.
1106 if (!release && dev->is_tape() && dev->has_cap(CAP_AUTOMOUNT)) {
1107 Dmsg0(150, "(1)Ask=0\n");
1110 dev->VolCatInfo.VolCatMounts++; /* Update mounts */
1111 Dmsg1(150, "update volinfo mounts=%d\n", dev->VolCatInfo.VolCatMounts);
1112 - if (!dir_update_volume_info(dcr, false)) {
1113 + if (!dir_update_volume_info(dcr, false, false)) {
1118 Dmsg0(150, "dir_update_vol_info. Set Append\n");
1119 /* Copy Director's info into the device info */
1120 dev->VolCatInfo = dcr->VolCatInfo; /* structure assignment */
1121 - if (!dir_update_volume_info(dcr, true)) { /* indicate tape labeled */
1122 + if (!dir_update_volume_info(dcr, true, true)) { /* indicate tape labeled */
1125 Jmsg(dcr->jcr, M_INFO, 0, _("Labeled new Volume \"%s\" on device %s.\n"),
1127 dev->VolCatInfo = dcr->VolCatInfo; /* structure assignment */
1128 bstrncpy(dev->VolCatInfo.VolCatStatus, "Error", sizeof(dev->VolCatInfo.VolCatStatus));
1129 Dmsg0(150, "dir_update_vol_info. Set Error.\n");
1130 - dir_update_volume_info(dcr, false);
1131 + dir_update_volume_info(dcr, false, false);
1136 dcr->VolCatInfo.InChanger = false;
1137 dev->VolCatInfo.InChanger = false;
1138 Dmsg0(400, "update vol info in mount\n");
1139 - dir_update_volume_info(dcr, true); /* set new status */
1140 + dir_update_volume_info(dcr, true, false); /* set new status */
1146 * First erase all memory of the current volume
1149 dev->block_num = dev->file = 0;
1150 dev->EndBlock = dev->EndFile = 0;
1151 memset(&dev->VolCatInfo, 0, sizeof(dev->VolCatInfo));
1152 diff -ur k1/src/stored/protos.h k3/src/stored/protos.h
1153 --- k1/src/stored/protos.h 2007-06-28 13:57:03.000000000 +0200
1154 +++ k3/src/stored/protos.h 2007-12-22 19:12:43.000000000 +0100
1157 * Protypes for stored -- Kern Sibbald MM
1159 - * Version $Id: protos.h 5112 2007-06-28 11:57:03Z kerns $
1160 + * Version $Id: protos.h 5852 2007-11-04 19:57:42Z kerns $
1166 bool dir_get_volume_info(DCR *dcr, enum get_vol_info_rw);
1167 bool dir_find_next_appendable_volume(DCR *dcr);
1168 -bool dir_update_volume_info(DCR *dcr, bool label);
1169 +bool dir_update_volume_info(DCR *dcr, bool label, bool update_LastWritten);
1170 bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr);
1171 bool dir_ask_sysop_to_mount_volume(DCR *dcr);
1172 bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec);
1174 bool is_this_bsr_done(BSR *bsr, DEV_RECORD *rec);
1177 -bool mount_next_write_volume(DCR *dcr, bool release);
1178 +bool mount_next_write_volume(DCR *dcr, bool have_vol, bool release);
1179 bool mount_next_read_volume(DCR *dcr);
1180 void mark_volume_in_error(DCR *dcr);
1182 diff -ur k1/src/stored/record.c k3/src/stored/record.c
1183 --- k1/src/stored/record.c 2007-06-07 16:46:43.000000000 +0200
1184 +++ k3/src/stored/record.c 2007-12-22 19:12:06.000000000 +0100
1188 - * record.c -- tape record handling functions
1190 - * Kern Sibbald, April MMI
1191 - * added BB02 format October MMII
1193 - * Version $Id: record.c 4992 2007-06-07 14:46:43Z kerns $
1197 Bacula® - The Network Backup Solution
1199 Copyright (C) 2001-2006 Free Software Foundation Europe e.V.
1201 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
1202 Switzerland, email:ftf@fsfeurope.org.
1206 + * record.c -- tape record handling functions
1208 + * Kern Sibbald, April MMI
1209 + * added BB02 format October MMII
1211 + * Version $Id: record.c 6014 2007-12-03 18:14:27Z kerns $
1218 ASSERT(block->buf_len >= block->binbuf);
1220 Dmsg6(890, "write_record_to_block() FI=%s SessId=%d Strm=%s len=%d\n"
1221 -"rem=%d remainder=%d\n",
1222 + "rem=%d remainder=%d\n",
1223 FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId,
1224 stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len,
1225 remlen, rec->remainder);
1227 if (!sm_check_rtn(__FILE__, __LINE__, False)) {
1228 /* We damaged a buffer */
1229 Dmsg6(0, "Damaged block FI=%s SessId=%d Strm=%s len=%d\n"
1230 -"rem=%d remainder=%d\n",
1231 + "rem=%d remainder=%d\n",
1232 FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId,
1233 stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len,
1234 remlen, rec->remainder);
1235 diff -ur k1/src/stored/reserve.c k3/src/stored/reserve.c
1236 --- k1/src/stored/reserve.c 2007-08-04 18:46:32.000000000 +0200
1237 +++ k3/src/stored/reserve.c 2007-12-22 19:09:56.000000000 +0100
1238 @@ -212,11 +212,11 @@
1240 len = Mmsg(msg, "%s on device %s\n", vol->vol_name, dev->print_name());
1241 sendit(msg.c_str(), len, arg);
1242 - len = Mmsg(msg, " Reader=%d writers=%d reserved=%d\n", dev->can_read()?1:0,
1243 - dev->num_writers, dev->reserved_device);
1244 + len = Mmsg(msg, " Reader=%d writers=%d reserved=%d released=%d\n",
1245 + dev->can_read()?1:0, dev->num_writers, dev->reserved_device, vol->released);
1246 sendit(msg.c_str(), len, arg);
1248 - len = Mmsg(msg, "%s no dev\n", vol->vol_name);
1249 + len = Mmsg(msg, "%s no device. released=%d\n", vol->vol_name, vol->released);
1250 sendit(msg.c_str(), len, arg);
1253 @@ -292,11 +292,11 @@
1254 * already exist and are correctly programmed and will need no changes -- use
1255 * counts are always very tricky.
1257 - * The old code had a concept of "reserving" a Volume, but it needs to be changed
1258 + * The old code had a concept of "reserving" a Volume, but was changed
1259 * to reserving and using a drive. A volume is must be attached to (owned by) a
1260 * drive and can move from drive to drive or be unused given certain specific
1261 * conditions of the drive. The key is that the drive must "own" the Volume.
1262 - * The old code has the job (dcr) owning the volume (more or less). The job is
1263 + * The old code had the job (dcr) owning the volume (more or less). The job was
1264 * to change the insertion and removal of the volumes from the list to be based
1265 * on the drive rather than the job.
1267 @@ -329,13 +329,14 @@
1268 * because it was probably inserted by another job.
1270 if (strcmp(vol->vol_name, VolumeName) == 0) {
1271 + Dmsg1(dbglvl, "OK, vol=%s on device.\n", VolumeName);
1272 goto get_out; /* Volume already on this device */
1274 - Dmsg3(dbglvl, "jid=%u reserve_vol free vol=%s at %p\n",
1275 + Dmsg3(dbglvl, "jid=%u reserve_vol free vol=%s at %p\n",
1276 (int)dcr->jcr->JobId, vol->vol_name, vol->vol_name);
1277 - debug_list_volumes("reserve_vol free");
1278 vol_list->remove(vol);
1280 + debug_list_volumes("reserve_vol free");
1284 @@ -378,12 +379,16 @@
1285 Dmsg4(dbglvl, "jid=%u Volume busy could not swap vol=%s from dev=%s to %s\n",
1286 jid(), VolumeName, vol->dev->print_name(), dev->print_name());
1287 vol = NULL; /* device busy */
1296 + vol->released = false;
1298 debug_list_volumes("end new volume");
1302 * explicitly read in this drive. This allows the SD to remember
1303 * where the tapes are or last were.
1305 + dev->vol->released = true;
1306 if (dev->is_tape() || dev->is_autochanger()) {
1310 dlist *temp_vol_list, *save_vol_list;
1313 + Dmsg0(dbglvl, "lock volumes\n");
1316 * Create a temporary copy of the volume list. We do this,
1317 @@ -1122,6 +1129,26 @@
1319 if (dcr->volume_in_use && !rctx.PreferMountedVols) {
1320 rctx.PreferMountedVols = true;
1321 + if (dcr->VolumeName[0]) {
1322 + volume_unused(dcr);
1327 + * Note. Under some circumstances, the Director can hand us
1328 + * a Volume name that is no the same as the one on the current
1329 + * drive, and in that case, the call above to find the next
1330 + * volume will fail because in attempting to reserve the Volume
1331 + * the code will realize that we already have a tape mounted,
1332 + * and it will fail. This *should* only happen if there are
1333 + * writers, thus the following test. In that case, we simply
1334 + * bail out, and continue waiting, rather than plunging on
1335 + * and hoping that the operator can resolve the problem.
1337 + if (dcr->dev->num_writers != 0) {
1338 + if (dcr->VolumeName[0]) {
1339 + volume_unused(dcr);
1344 @@ -1270,6 +1297,51 @@
1348 +static int is_pool_ok(DCR *dcr)
1350 + DEVICE *dev = dcr->dev;
1351 + JCR *jcr = dcr->jcr;
1353 + /* Now check if we want the same Pool and pool type */
1354 + if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
1355 + strcmp(dev->pool_type, dcr->pool_type) == 0) {
1356 + /* OK, compatible device */
1357 + Dmsg1(dbglvl, "OK dev: %s num_writers=0, reserved, pool matches\n", dev->print_name());
1360 + /* Drive Pool not suitable for us */
1361 + Mmsg(jcr->errmsg, _(
1362 +"3608 JobId=%u wants Pool=\"%s\" but have Pool=\"%s\" nreserve=%d on drive %s.\n"),
1363 + (uint32_t)jcr->JobId, dcr->pool_name, dev->pool_name,
1364 + dev->reserved_device, dev->print_name());
1365 + queue_reserve_message(jcr);
1366 + Dmsg2(dbglvl, "failed: busy num_writers=0, reserved, pool=%s wanted=%s\n",
1367 + dev->pool_name, dcr->pool_name);
1372 +static bool is_max_jobs_ok(DCR *dcr)
1374 + DEVICE *dev = dcr->dev;
1375 + JCR *jcr = dcr->jcr;
1377 + Dmsg4(dbglvl, "MaxJobs=%d Jobs=%d reserves=%d Vol=%s\n",
1378 + dcr->VolCatInfo.VolCatMaxJobs,
1379 + dcr->VolCatInfo.VolCatJobs, dev->reserved_device,
1381 + if (dcr->VolCatInfo.VolCatMaxJobs > 0 && dcr->VolCatInfo.VolCatMaxJobs <=
1382 + (dcr->VolCatInfo.VolCatJobs + dev->reserved_device)) {
1383 + /* Max Job Vols depassed or already reserved */
1384 + Mmsg(jcr->errmsg, _("3610 JobId=%u Volume max jobs exceeded on drive %s.\n"),
1385 + (uint32_t)jcr->JobId, dev->print_name());
1386 + queue_reserve_message(jcr);
1387 + Dmsg1(dbglvl, "reserve dev failed: %s", jcr->errmsg);
1388 + return false; /* wait */
1394 * Returns: 1 if drive can be reserved
1395 * 0 if we should wait
1396 @@ -1285,6 +1357,11 @@
1397 rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
1398 rctx.autochanger_only, rctx.any_drive);
1400 + /* Check for max jobs on this Volume */
1401 + if (!is_max_jobs_ok(dcr)) {
1405 /* setting any_drive overrides PreferMountedVols flag */
1406 if (!rctx.any_drive) {
1408 @@ -1374,32 +1451,10 @@
1409 if (dev->num_writers == 0) {
1410 /* Now check if there are any reservations on the drive */
1411 if (dev->reserved_device) {
1412 - /* Now check if we want the same Pool and pool type */
1413 - if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
1414 - strcmp(dev->pool_type, dcr->pool_type) == 0) {
1415 - /* OK, compatible device */
1416 - Dmsg2(dbglvl, "jid=%u OK dev: %s num_writers=0, reserved, pool matches\n",
1417 - jcr->JobId, dev->print_name());
1420 - /* Drive Pool not suitable for us */
1421 - Mmsg(jcr->errmsg, _(
1422 -"3608 JobId=%u wants Pool=\"%s\" but have Pool=\"%s\" nreserve=%d on drive %s.\n"),
1423 - jcr->JobId, dcr->pool_name, dev->pool_name,
1424 - dev->reserved_device, dev->print_name());
1425 - queue_reserve_message(jcr);
1426 - Dmsg3(dbglvl, "jid=%u failed: busy num_writers=0, reserved, pool=%s wanted=%s\n",
1427 - (int)jcr->JobId, dev->pool_name, dcr->pool_name);
1428 - return 0; /* wait */
1430 + return is_pool_ok(dcr);
1431 } else if (dev->can_append()) {
1432 - /* Device in append mode, check if changing pool */
1433 - if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
1434 - strcmp(dev->pool_type, dcr->pool_type) == 0) {
1435 - Dmsg2(dbglvl, "jid=%u OK dev: %s num_writers=0, can_append, pool matches.\n",
1436 - jcr->JobId, dev->print_name());
1437 - /* OK, compatible device */
1439 + if (is_pool_ok(dcr)) {
1442 /* Changing pool, unload old tape if any in drive */
1443 Dmsg1(dbglvl, "jid=%u OK dev: num_writers=0, not reserved, pool change, unload changer\n",
1444 @@ -1419,22 +1474,7 @@
1445 * available if pool is the same).
1447 if (dev->can_append() || dev->num_writers > 0) {
1448 - /* Yes, now check if we want the same Pool and pool type */
1449 - if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
1450 - strcmp(dev->pool_type, dcr->pool_type) == 0) {
1451 - Dmsg2(dbglvl, "jid=%u OK dev: %s num_writers>=0, can_append, pool matches.\n",
1452 - jcr->JobId, dev->print_name());
1453 - /* OK, compatible device */
1456 - /* Drive Pool not suitable for us */
1457 - Mmsg(jcr->errmsg, _("3609 JobId=%u wants Pool=\"%s\" but has Pool=\"%s\" on drive %s.\n"),
1458 - jcr->JobId, dcr->pool_name, dev->pool_name, dev->print_name());
1459 - queue_reserve_message(jcr);
1460 - Dmsg3(dbglvl, "jid=%u failed: busy num_writers>0, can_append, pool=%s wanted=%s\n",
1461 - (int)jcr->JobId, dev->pool_name, dcr->pool_name);
1462 - return 0; /* wait */
1464 + return is_pool_ok(dcr);
1466 Pmsg1(000, _("Logic error!!!! JobId=%u Should not get here.\n"), (int)jcr->JobId);
1467 Mmsg(jcr->errmsg, _("3910 JobId=%u Logic error!!!! drive %s Should not get here.\n"),