]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/acquire.c
Merge branch 'master' into basejobv3
[bacula/bacula] / bacula / src / stored / acquire.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2002-2009 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version two of the GNU General Public
10    License as published by the Free Software Foundation and included
11    in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of Kern Sibbald.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 /*
29  *  Routines to acquire and release a device for read/write
30  *
31  *   Kern Sibbald, August MMII
32  *
33  *   Version $Id$
34  */
35
36 #include "bacula.h"                   /* pull in global headers */
37 #include "stored.h"                   /* pull in Storage Deamon headers */
38
39 /* Forward referenced functions */
40 static void attach_dcr_to_dev(DCR *dcr);
41 static void set_dcr_from_vol(DCR *dcr, VOL_LIST *vol);
42
43
44 /*********************************************************************
45  * Acquire device for reading. 
46  *  The drive should have previously been reserved by calling 
47  *  reserve_device_for_read(). We read the Volume label from the block and
48  *  leave the block pointers just after the label.
49  *
50  *  Returns: NULL if failed for any reason
51  *           dcr  if successful
52  */
53 bool acquire_device_for_read(DCR *dcr)
54 {
55    DEVICE *dev = dcr->dev;
56    JCR *jcr = dcr->jcr;
57    bool ok = false;
58    bool tape_previously_mounted;
59    bool tape_initially_mounted;
60    VOL_LIST *vol;
61    bool try_autochanger = true;
62    int i;
63    int vol_label_status;
64    int retry = 0;
65    
66    Dmsg1(950, "jcr->dcr=%p\n", jcr->dcr);
67    dev->dblock(BST_DOING_ACQUIRE);
68
69    if (dev->num_writers > 0) {
70       Jmsg2(jcr, M_FATAL, 0, _("Acquire read: num_writers=%d not zero. Job %d canceled.\n"), 
71          dev->num_writers, jcr->JobId);
72       goto get_out;
73    }
74
75    /* Find next Volume, if any */
76    vol = jcr->VolList;
77    if (!vol) {
78       char ed1[50];
79       Jmsg(jcr, M_FATAL, 0, _("No volumes specified for reading. Job %s canceled.\n"), 
80          edit_int64(jcr->JobId, ed1));
81       goto get_out;
82    }
83    jcr->CurReadVolume++;
84    for (i=1; i<jcr->CurReadVolume; i++) {
85       vol = vol->next;
86    }
87    if (!vol) {
88       Jmsg(jcr, M_FATAL, 0, _("Logic error: no next volume to read. Numvol=%d Curvol=%d\n"),
89          jcr->NumReadVolumes, jcr->CurReadVolume);
90       goto get_out;                   /* should not happen */   
91    }
92    set_dcr_from_vol(dcr, vol);
93
94    Dmsg2(100, "Want Vol=%s Slot=%d\n", vol->VolumeName, vol->Slot);
95     
96    /*
97     * If the MediaType requested for this volume is not the
98     *  same as the current drive, we attempt to find the same
99     *  device that was used to write the orginal volume.  If
100     *  found, we switch to using that device.
101     *
102     *  N.B. A lot of routines rely on the dcr pointer not changing
103     *    read_records.c even has multiple dcrs cached, so we take care
104     *    here to release all important parts of the dcr and re-acquire
105     *    them such as the block pointer (size may change), but we do
106     *    not release the dcr.
107     */
108    Dmsg2(50, "MediaType dcr=%s dev=%s\n", dcr->media_type, dev->device->media_type);
109    if (dcr->media_type[0] && strcmp(dcr->media_type, dev->device->media_type) != 0) {
110       RCTX rctx;
111       DIRSTORE *store;
112       int stat;
113
114       Jmsg3(jcr, M_INFO, 0, _("Changing read device. Want Media Type=\"%s\" have=\"%s\"\n"
115                               "  device=%s\n"), 
116             dcr->media_type, dev->device->media_type, dev->print_name());
117       Dmsg3(50, "Changing read device. Want Media Type=\"%s\" have=\"%s\"\n"
118                               "  device=%s\n", 
119             dcr->media_type, dev->device->media_type, dev->print_name());
120
121       dev->dunblock(DEV_UNLOCKED);
122
123       lock_reservations();
124       memset(&rctx, 0, sizeof(RCTX));
125       rctx.jcr = jcr;
126       jcr->reserve_msgs = New(alist(10, not_owned_by_alist));
127       rctx.any_drive = true;
128       rctx.device_name = vol->device;
129       store = new DIRSTORE;
130       memset(store, 0, sizeof(DIRSTORE));
131       store->name[0] = 0; /* No dir name */
132       bstrncpy(store->media_type, vol->MediaType, sizeof(store->media_type));
133       bstrncpy(store->pool_name, dcr->pool_name, sizeof(store->pool_name));
134       bstrncpy(store->pool_type, dcr->pool_type, sizeof(store->pool_type));
135       store->append = false;
136       rctx.store = store;
137       clean_device(dcr);                     /* clean up the dcr */
138       
139       /*
140        * Search for a new device
141        */
142       stat = search_res_for_device(rctx);
143       release_reserve_messages(jcr);         /* release queued messages */
144       unlock_reservations();
145
146       if (stat == 1) {
147          dev = dcr->dev;                     /* get new device pointer */
148          dev->dblock(BST_DOING_ACQUIRE); 
149          dcr->VolumeName[0] = 0;
150          Jmsg(jcr, M_INFO, 0, _("Media Type change.  New read device %s chosen.\n"),
151             dev->print_name());
152          Dmsg1(50, "Media Type change.  New read device %s chosen.\n", dev->print_name());
153
154          bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
155          bstrncpy(dcr->VolCatInfo.VolCatName, vol->VolumeName, sizeof(dcr->VolCatInfo.VolCatName));
156          bstrncpy(dcr->media_type, vol->MediaType, sizeof(dcr->media_type));
157          dcr->VolCatInfo.Slot = vol->Slot;
158          dcr->VolCatInfo.InChanger = vol->Slot > 0; 
159          bstrncpy(dcr->pool_name, store->pool_name, sizeof(dcr->pool_name));
160          bstrncpy(dcr->pool_type, store->pool_type, sizeof(dcr->pool_type));
161       } else {
162          /* error */
163          Jmsg1(jcr, M_FATAL, 0, _("No suitable device found to read Volume \"%s\"\n"),
164             vol->VolumeName);
165          Dmsg1(50, "No suitable device found to read Volume \"%s\"\n", vol->VolumeName);
166          goto get_out;
167       }
168    }
169
170    dev->clear_unload();
171
172    if (dev->vol && dev->vol->is_swapping()) {
173       dev->vol->set_slot(vol->Slot);
174       Dmsg3(100, "swapping: slot=%d Vol=%s dev=%s\n", dev->vol->get_slot(),
175          dev->vol->vol_name, dev->print_name());
176    }
177
178    init_device_wait_timers(dcr);
179
180    tape_previously_mounted = dev->can_read() || dev->can_append() ||
181                              dev->is_labeled();
182    tape_initially_mounted = tape_previously_mounted;
183
184
185    /* Volume info is always needed because of VolParts */
186    Dmsg1(150, "dir_get_volume_info vol=%s\n", dcr->VolumeName);
187    if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_READ)) {
188       Dmsg2(150, "dir_get_vol_info failed for vol=%s: %s\n", 
189          dcr->VolumeName, jcr->errmsg);
190       Jmsg1(jcr, M_WARNING, 0, "Read acquire: %s", jcr->errmsg);
191    }
192    dev->set_load();                /* set to load volume */
193    
194    for ( ;; ) {
195       /* If not polling limit retries */
196       if (!dev->poll && retry++ > 10) {
197          break;
198       }
199       dev->clear_labeled();              /* force reread of label */
200       if (job_canceled(jcr)) {
201          char ed1[50];
202          Mmsg1(dev->errmsg, _("Job %s canceled.\n"), edit_int64(jcr->JobId, ed1));
203          Jmsg(jcr, M_INFO, 0, dev->errmsg);
204          goto get_out;                /* error return */
205       }
206
207       dcr->do_unload();
208       dcr->do_swapping(false/*!is_writing*/);
209       dcr->do_load(false /*!is_writing*/);
210       set_dcr_from_vol(dcr, vol);          /* refresh dcr with desired volume info */
211
212       /*
213        * This code ensures that the device is ready for
214        * reading. If it is a file, it opens it.
215        * If it is a tape, it checks the volume name
216        */
217       Dmsg1(100, "bstored: open vol=%s\n", dcr->VolumeName);
218       if (dev->open(dcr, OPEN_READ_ONLY) < 0) {
219          if (!dev->poll) {
220             Jmsg3(jcr, M_WARNING, 0, _("Read open device %s Volume \"%s\" failed: ERR=%s\n"),
221                   dev->print_name(), dcr->VolumeName, dev->bstrerror());
222          }
223          goto default_path;
224       }
225       Dmsg1(50, "opened dev %s OK\n", dev->print_name());
226       
227       /* Read Volume Label */
228       Dmsg0(50, "calling read-vol-label\n");
229       vol_label_status = read_dev_volume_label(dcr);
230       switch (vol_label_status) {
231       case VOL_OK:
232          Dmsg0(50, "Got correct volume.\n");
233          ok = true;
234          dev->VolCatInfo = dcr->VolCatInfo;     /* structure assignment */
235          break;                    /* got it */
236       case VOL_IO_ERROR:
237          Dmsg0(50, "IO Error\n");
238          /*
239           * Send error message generated by read_dev_volume_label()
240           *  only we really had a tape mounted. This supresses superfluous
241           *  error messages when nothing is mounted.
242           */
243          if (tape_previously_mounted) {
244             Jmsg(jcr, M_WARNING, 0, "Read acquire: %s", jcr->errmsg);
245          }
246          goto default_path;
247       case VOL_NAME_ERROR:
248          Dmsg3(50, "Vol name=%s want=%s drv=%s.\n", dev->VolHdr.VolumeName, 
249                dcr->VolumeName, dev->print_name());
250          if (dev->is_volume_to_unload()) {
251             goto default_path;
252          }
253          dev->set_unload();              /* force unload of unwanted tape */
254          if (!unload_autochanger(dcr, -1)) {
255             /* at least free the device so we can re-open with correct volume */
256             dev->close();                                                          
257             free_volume(dev);
258          }
259          dev->set_load();
260          /* Fall through */
261       default:
262          Jmsg1(jcr, M_WARNING, 0, "Read acquire: %s", jcr->errmsg);
263 default_path:
264          Dmsg0(50, "default path\n");
265          tape_previously_mounted = true;
266          
267          /*
268           * If the device requires mount, close it, so the device can be ejected.
269           */
270          if (dev->requires_mount()) {
271             dev->close();
272             free_volume(dev);
273          }
274          
275          /* Call autochanger only once unless ask_sysop called */
276          if (try_autochanger) {
277             int stat;
278             Dmsg2(200, "calling autoload Vol=%s Slot=%d\n",
279                dcr->VolumeName, dcr->VolCatInfo.Slot);
280             stat = autoload_device(dcr, 0, NULL);
281             if (stat > 0) {
282                try_autochanger = false;
283                continue;              /* try reading volume mounted */
284             }
285          }
286          
287          /* Mount a specific volume and no other */
288          Dmsg0(200, "calling dir_ask_sysop\n");
289          if (!dir_ask_sysop_to_mount_volume(dcr, ST_READ)) {
290             goto get_out;             /* error return */
291          }
292
293          /* Volume info is always needed because of VolParts */
294          Dmsg1(150, "dir_get_volume_info vol=%s\n", dcr->VolumeName);
295          if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_READ)) {
296             Dmsg2(150, "dir_get_vol_info failed for vol=%s: %s\n", 
297                   dcr->VolumeName, jcr->errmsg);
298             Jmsg1(jcr, M_WARNING, 0, "Read acquire: %s", jcr->errmsg);
299          }
300          dev->set_load();                /* set to load volume */
301
302          try_autochanger = true;      /* permit trying the autochanger again */
303
304          continue;                    /* try reading again */
305       } /* end switch */
306       break;
307    } /* end for loop */
308
309    if (!ok) {
310       Jmsg1(jcr, M_FATAL, 0, _("Too many errors trying to mount device %s for reading.\n"),
311             dev->print_name());
312       goto get_out;
313    }
314
315    dev->clear_append();
316    dev->set_read();
317    set_jcr_job_status(jcr, JS_Running);
318    dir_send_job_status(jcr);
319    Jmsg(jcr, M_INFO, 0, _("Ready to read from volume \"%s\" on device %s.\n"),
320       dcr->VolumeName, dev->print_name());
321
322 get_out:
323    dev->dlock();
324    dcr->clear_reserved();
325    /* 
326     * Normally we are blocked, but in at least one error case above 
327     *   we are not blocked because we unsuccessfully tried changing
328     *   devices.  
329     */
330    if (dev->is_blocked()) {
331       dev->dunblock(DEV_LOCKED);
332    } else {
333       dev->dunlock();               /* dunblock() unlock the device too */
334    }
335    Dmsg1(950, "jcr->dcr=%p\n", jcr->dcr);
336    return ok;
337 }
338
339 /*
340  * Acquire device for writing. We permit multiple writers.
341  *  If this is the first one, we read the label.
342  *
343  *  Returns: NULL if failed for any reason
344  *           dcr if successful.
345  *   Note, normally reserve_device_for_append() is called
346  *   before this routine.
347  */
348 DCR *acquire_device_for_append(DCR *dcr)
349 {
350    DEVICE *dev = dcr->dev;
351    JCR *jcr = dcr->jcr;
352    bool ok = false;
353    bool have_vol = false;
354
355    init_device_wait_timers(dcr);
356
357    P(dev->acquire_mutex);           /* only one job at a time */
358    dev->dlock();
359    Dmsg1(100, "acquire_append device is %s\n", dev->is_tape()?"tape":
360         (dev->is_dvd()?"DVD":"disk"));
361
362    /*
363     * With the reservation system, this should not happen
364     */
365    if (dev->can_read()) {
366       Jmsg1(jcr, M_FATAL, 0, _("Want to append, but device %s is busy reading.\n"), dev->print_name());
367       Dmsg1(200, "Want to append but device %s is busy reading.\n", dev->print_name());
368       goto get_out;
369    }
370
371    dev->clear_unload();
372
373    /*
374     * have_vol defines whether or not mount_next_write_volume should
375     *   ask the Director again about what Volume to use.
376     */
377    if (dev->can_append() && dcr->is_suitable_volume_mounted() &&
378        strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") != 0) {
379       Dmsg0(190, "device already in append.\n");
380       /*
381        * At this point, the correct tape is already mounted, so
382        *   we do not need to do mount_next_write_volume(), unless
383        *   we need to recycle the tape.
384        */
385        if (dev->num_writers == 0) {
386           memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
387        }
388        have_vol = dcr->is_tape_position_ok();
389    }
390
391    if (!have_vol) {
392       dev->r_dlock(true);
393       block_device(dev, BST_DOING_ACQUIRE);
394       dev->dunlock();
395       Dmsg1(190, "jid=%u Do mount_next_write_vol\n", (uint32_t)jcr->JobId);
396       if (!dcr->mount_next_write_volume()) {
397          if (!job_canceled(jcr)) {
398             /* Reduce "noise" -- don't print if job canceled */
399             Jmsg(jcr, M_FATAL, 0, _("Could not ready device %s for append.\n"),
400                dev->print_name());
401             Dmsg1(200, "Could not ready device %s for append.\n", 
402                dev->print_name());
403          }
404          dev->dlock();
405          unblock_device(dev);
406          goto get_out;
407       }
408       Dmsg2(190, "Output pos=%u:%u\n", dcr->dev->file, dcr->dev->block_num);
409       dev->dlock();
410       unblock_device(dev);
411    }
412
413    dev->num_writers++;                /* we are now a writer */
414    if (jcr->NumWriteVolumes == 0) {
415       jcr->NumWriteVolumes = 1;
416    }
417    dev->VolCatInfo.VolCatJobs++;              /* increment number of jobs on vol */
418    Dmsg4(100, "=== nwriters=%d nres=%d vcatjob=%d dev=%s\n", 
419       dev->num_writers, dev->num_reserved(), dev->VolCatInfo.VolCatJobs, 
420       dev->print_name());
421    dir_update_volume_info(dcr, false, false); /* send Volume info to Director */
422    ok = true;
423
424 get_out:
425    dcr->clear_reserved();
426    dev->dunlock();
427    V(dev->acquire_mutex);
428    return ok ? dcr : NULL;
429 }
430
431 /*
432  * This job is done, so release the device. From a Unix standpoint,
433  *  the device remains open.
434  *
435  * Note, if we are spooling, we may enter with the device locked.
436  * However, in all cases, unlock the device when leaving.
437  *
438  */
439 bool release_device(DCR *dcr)
440 {
441    JCR *jcr = dcr->jcr;
442    DEVICE *dev = dcr->dev;
443    bool ok = true;
444    char tbuf[100];
445
446    /* lock only if not already locked by this thread */
447    if (!dcr->is_dev_locked()) {
448       dev->r_dlock();
449    }
450    lock_volumes();
451    Dmsg2(100, "release_device device %s is %s\n", dev->print_name(), dev->is_tape()?"tape":"disk");
452
453    /* if device is reserved, job never started, so release the reserve here */
454    dcr->clear_reserved();
455
456    if (dev->can_read()) {
457       VOLUME_CAT_INFO *vol = &dev->VolCatInfo;
458       dev->clear_read();              /* clear read bit */
459       Dmsg2(150, "dir_update_vol_info. label=%d Vol=%s\n",
460          dev->is_labeled(), vol->VolCatName);
461       if (dev->is_labeled() && vol->VolCatName[0] != 0) {
462          dir_update_volume_info(dcr, false, false); /* send Volume info to Director */
463          remove_read_volume(jcr, dcr->VolumeName);
464          volume_unused(dcr);
465       }
466    } else if (dev->num_writers > 0) {
467       /* 
468        * Note if WEOT is set, we are at the end of the tape
469        *   and may not be positioned correctly, so the
470        *   job_media_record and update_vol_info have already been
471        *   done, which means we skip them here.
472        */
473       dev->num_writers--;
474       Dmsg1(100, "There are %d writers in release_device\n", dev->num_writers);
475       if (dev->is_labeled()) {
476          Dmsg2(200, "dir_create_jobmedia. Release vol=%s dev=%s\n", 
477                dev->VolCatInfo.VolCatName, dev->print_name());
478          if (!dev->at_weot() && !dir_create_jobmedia_record(dcr)) {
479             Jmsg2(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
480                dcr->VolCatInfo.VolCatName, jcr->Job);
481          }
482          /* If no more writers, and no errors, and wrote something, write an EOF */
483          if (!dev->num_writers && dev->can_write() && dev->block_num > 0) {
484             dev->weof(1);
485             write_ansi_ibm_labels(dcr, ANSI_EOF_LABEL, dev->VolHdr.VolumeName);
486          }
487          if (!dev->at_weot()) {
488             dev->VolCatInfo.VolCatFiles = dev->file;   /* set number of files */
489             /* Note! do volume update before close, which zaps VolCatInfo */
490             dir_update_volume_info(dcr, false, false); /* send Volume info to Director */
491             Dmsg2(200, "dir_update_vol_info. Release vol=%s dev=%s\n", 
492                   dev->VolCatInfo.VolCatName, dev->print_name());
493          }
494          if (dev->num_writers == 0) {         /* if not being used */
495             volume_unused(dcr);               /*  we obviously are not using the volume */
496          }
497       }
498
499    } else {
500       /*                
501        * If we reach here, it is most likely because the job
502        *   has failed, since the device is not in read mode and
503        *   there are no writers. It was probably reserved.
504        */
505       volume_unused(dcr);
506    }
507    unlock_volumes();
508    Dmsg3(100, "%d writers, %d reserve, dev=%s\n", dev->num_writers, dev->num_reserved(),
509          dev->print_name());
510    debug_list_volumes("acquire:release_device()");
511
512
513    /* If no writers, close if file or !CAP_ALWAYS_OPEN */
514    if (dev->num_writers == 0 && (!dev->is_tape() || !dev->has_cap(CAP_ALWAYSOPEN))) {
515       dvd_remove_empty_part(dcr);        /* get rid of any empty spool part */
516       dev->close();
517       free_volume(dev);
518    }
519
520    /* Fire off Alert command and include any output */
521    if (!job_canceled(jcr) && dcr->device->alert_command) {
522       POOLMEM *alert;
523       int status = 1;
524       BPIPE *bpipe;
525       char line[MAXSTRING];
526       alert = get_pool_memory(PM_FNAME);
527       alert = edit_device_codes(dcr, alert, dcr->device->alert_command, "");
528       bpipe = open_bpipe(alert, 0, "r");
529       if (bpipe) {
530          while (fgets(line, sizeof(line), bpipe->rfd)) {
531             Jmsg(jcr, M_ALERT, 0, _("Alert: %s"), line);
532          }
533          status = close_bpipe(bpipe);
534       } else {
535          status = errno;
536       }
537       if (status != 0) {
538          berrno be;
539          Jmsg(jcr, M_ALERT, 0, _("3997 Bad alert command: %s: ERR=%s.\n"),
540               alert, be.bstrerror(status));
541       }
542
543       Dmsg1(400, "alert status=%d\n", status);
544       free_pool_memory(alert);
545    }
546    pthread_cond_broadcast(&dev->wait_next_vol);
547    Dmsg2(100, "JobId=%u broadcast wait_device_release at %s\n", 
548          (uint32_t)jcr->JobId, bstrftimes(tbuf, sizeof(tbuf), (utime_t)time(NULL)));
549    pthread_cond_broadcast(&wait_device_release);
550    dev->dunlock();
551    if (dcr->keep_dcr) {
552       detach_dcr_from_dev(dcr);
553    } else {
554       if (jcr->read_dcr == dcr) {
555          jcr->read_dcr = NULL;
556       }
557       if (jcr->dcr == dcr) {
558          jcr->dcr = NULL;
559       }
560       free_dcr(dcr);
561    }
562    Dmsg2(100, "===== Device %s released by JobId=%u\n", dev->print_name(),
563          (uint32_t)jcr->JobId);
564    return ok;
565 }
566
567 /*
568  * Clean up the device for reuse without freeing the memory
569  */
570 bool clean_device(DCR *dcr)
571 {
572    bool ok;
573    dcr->keep_dcr = true;                  /* do not free the dcr */
574    ok = release_device(dcr);
575    dcr->keep_dcr = false;
576    return ok;
577 }
578
579 /*
580  * Create a new Device Control Record and attach
581  *   it to the device (if this is a real job).
582  * Note, this has been updated so that it can be called first 
583  *   without a DEVICE, then a second or third time with a DEVICE,
584  *   and each time, it should cleanup and point to the new device.
585  *   This should facilitate switching devices.
586  * Note, each dcr must point to the controlling job (jcr).  However,
587  *   a job can have multiple dcrs, so we must not store in the jcr's
588  *   structure as previously. The higher level routine must store
589  *   this dcr in the right place
590  *
591  */
592 DCR *new_dcr(JCR *jcr, DCR *dcr, DEVICE *dev)
593 {
594    if (!dcr) {
595       dcr = (DCR *)malloc(sizeof(DCR));
596       memset(dcr, 0, sizeof(DCR));
597       dcr->tid = pthread_self();
598       dcr->spool_fd = -1;
599    }
600    dcr->jcr = jcr;                 /* point back to jcr */
601    /* Set device information, possibly change device */
602    if (dev) {
603       if (dcr->block) {
604          free_block(dcr->block);
605       }
606       dcr->block = new_block(dev);
607       if (dcr->rec) {
608          free_record(dcr->rec);
609       }
610       dcr->rec = new_record();
611       if (dcr->attached_to_dev) {
612          detach_dcr_from_dev(dcr);
613       }
614       /* Use job spoolsize prior to device spoolsize */
615       if (jcr->spool_size) {
616          dcr->max_job_spool_size = jcr->spool_size;
617       } else {
618          dcr->max_job_spool_size = dev->device->max_job_spool_size;
619       }
620       dcr->device = dev->device;
621       dcr->dev = dev;
622       attach_dcr_to_dev(dcr);
623    }
624    return dcr;
625 }
626
627 /*
628  * Search the dcrs list for the given dcr. If it is found,
629  *  as it should be, then remove it. Also zap the jcr pointer
630  *  to the dcr if it is the same one.
631  *
632  * Note, this code will be turned on when we can write to multiple
633  *  dcrs at the same time.
634  */
635 #ifdef needed
636 static void remove_dcr_from_dcrs(DCR *dcr)
637 {
638    JCR *jcr = dcr->jcr;
639    if (jcr->dcrs) {
640       int i = 0;
641       DCR *ldcr;
642       int num = jcr->dcrs->size();
643       for (i=0; i < num; i++) {
644          ldcr = (DCR *)jcr->dcrs->get(i);
645          if (ldcr == dcr) {
646             jcr->dcrs->remove(i);
647             if (jcr->dcr == dcr) {
648                jcr->dcr = NULL;
649             }
650          }
651       }
652    }
653 }
654 #endif
655
656 static void attach_dcr_to_dev(DCR *dcr)
657 {
658    DEVICE *dev = dcr->dev;
659    JCR *jcr = dcr->jcr;
660
661    if (jcr) Dmsg1(500, "JobId=%u enter attach_dcr_to_dev\n", (uint32_t)jcr->JobId);
662    if (!dcr->attached_to_dev && dev->initiated && jcr && jcr->get_JobType() != JT_SYSTEM) {
663       dev->attached_dcrs->append(dcr);  /* attach dcr to device */
664       dcr->attached_to_dev = true;
665       Dmsg1(500, "JobId=%u attach_dcr_to_dev\n", (uint32_t)jcr->JobId);
666    }
667 }
668
669 void detach_dcr_from_dev(DCR *dcr)
670 {
671    DEVICE *dev = dcr->dev;
672    Dmsg0(500, "Enter detach_dcr_from_dev\n"); /* jcr is NULL in some cases */
673
674    /* Detach this dcr only if attached */
675    if (dcr->attached_to_dev && dev) {
676       dev->dlock();
677       dcr->unreserve_device();
678       dcr->dev->attached_dcrs->remove(dcr);  /* detach dcr from device */
679       dcr->attached_to_dev = false;
680 //    remove_dcr_from_dcrs(dcr);      /* remove dcr from jcr list */
681       dev->dunlock();
682    }
683 }
684
685 /*
686  * Free up all aspects of the given dcr -- i.e. dechain it,
687  *  release allocated memory, zap pointers, ...
688  */
689 void free_dcr(DCR *dcr)
690 {
691    JCR *jcr = dcr->jcr;
692
693    detach_dcr_from_dev(dcr);
694
695    if (dcr->block) {
696       free_block(dcr->block);
697    }
698    if (dcr->rec) {
699       free_record(dcr->rec);
700    }
701    if (jcr && jcr->dcr == dcr) {
702       jcr->dcr = NULL;
703    }
704    free(dcr);
705 }
706
707 static void set_dcr_from_vol(DCR *dcr, VOL_LIST *vol)
708 {
709    /*    
710     * Note, if we want to be able to work from a .bsr file only          
711     *  for disaster recovery, we must "simulate" reading the catalog
712     */
713    bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
714    bstrncpy(dcr->VolCatInfo.VolCatName, vol->VolumeName, sizeof(dcr->VolCatInfo.VolCatName));
715    bstrncpy(dcr->media_type, vol->MediaType, sizeof(dcr->media_type));
716    dcr->VolCatInfo.Slot = vol->Slot;
717    dcr->VolCatInfo.InChanger = vol->Slot > 0; 
718 }