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