]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/acquire.c
fd9e53fb38438f2ce06b73daab63f689f917883b
[bacula/bacula] / bacula / src / stored / acquire.c
1 /*
2  *  Routines to acquire and release a device for read/write
3  *
4  *   Kern Sibbald, August MMII
5  *
6  *   Version $Id$
7  */
8 /*
9    Copyright (C) 2002-2006 Kern Sibbald
10
11    This program is free software; you can redistribute it and/or
12    modify it under the terms of the GNU General Public License
13    version 2 as amended with additional clauses defined in the
14    file LICENSE in the main source directory.
15
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
19    the file LICENSE for additional details.
20
21  */
22
23 #include "bacula.h"                   /* pull in global headers */
24 #include "stored.h"                   /* pull in Storage Deamon headers */
25
26 /* Forward referenced functions */
27 static void attach_dcr_to_dev(DCR *dcr);
28
29
30 /*********************************************************************
31  * Acquire device for reading. 
32  *  The drive should have previously been reserved by calling 
33  *  reserve_device_for_read(). We read the Volume label from the block and
34  *  leave the block pointers just after the label.
35  *
36  *  Returns: NULL if failed for any reason
37  *           dcr  if successful
38  */
39 bool acquire_device_for_read(DCR *dcr)
40 {
41    DEVICE *dev = dcr->dev;
42    JCR *jcr = dcr->jcr;
43    bool ok = false;
44    bool tape_previously_mounted;
45    bool tape_initially_mounted;
46    VOL_LIST *vol;
47    bool try_autochanger = true;
48    int i;
49    int vol_label_status;
50    int retry = 0;
51    
52    Dmsg1(50, "jcr->dcr=%p\n", jcr->dcr);
53    dev->block(BST_DOING_ACQUIRE);
54
55    if (dev->num_writers > 0) {
56       Jmsg2(jcr, M_FATAL, 0, _("Num_writers=%d not zero. Job %d canceled.\n"), 
57          dev->num_writers, jcr->JobId);
58       goto get_out;
59    }
60
61    /* Find next Volume, if any */
62    vol = jcr->VolList;
63    if (!vol) {
64       Jmsg(jcr, M_FATAL, 0, _("No volumes specified. Job %d canceled.\n"), jcr->JobId);
65       goto get_out;
66    }
67    jcr->CurVolume++;
68    for (i=1; i<jcr->CurVolume; i++) {
69       vol = vol->next;
70    }
71    if (!vol) {
72       goto get_out;                   /* should not happen */   
73    }
74    bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
75    bstrncpy(dcr->media_type, vol->MediaType, sizeof(dcr->media_type));
76    dcr->VolCatInfo.Slot = vol->Slot;
77     
78    /*
79     * If the MediaType requested for this volume is not the
80     *  same as the current drive, we attempt to find the same
81     *  device that was used to write the orginal volume.  If
82     *  found, we switch to using that device.
83     */
84    Dmsg2(100, "MediaType dcr=%s dev=%s\n", dcr->media_type, dev->device->media_type);
85    if (dcr->media_type[0] && strcmp(dcr->media_type, dev->device->media_type) != 0) {
86       RCTX rctx;
87       DIRSTORE *store;
88       int stat;
89       DCR *dcr_save = jcr->dcr;
90
91       lock_reservations();
92       jcr->dcr = NULL;
93       memset(&rctx, 0, sizeof(RCTX));
94       rctx.jcr = jcr;
95       jcr->reserve_msgs = New(alist(10, not_owned_by_alist));
96       rctx.any_drive = true;
97       rctx.device_name = vol->device;
98       store = new DIRSTORE;
99       memset(store, 0, sizeof(DIRSTORE));
100       store->name[0] = 0; /* No dir name */
101       bstrncpy(store->media_type, vol->MediaType, sizeof(store->media_type));
102       bstrncpy(store->pool_name, dcr->pool_name, sizeof(store->pool_name));
103       bstrncpy(store->pool_type, dcr->pool_type, sizeof(store->pool_type));
104       store->append = false;
105       rctx.store = store;
106       
107       /*
108        * Note, if search_for_device() succeeds, we get a new_dcr,
109        *  which we do not use except for the dev info.
110        */
111       stat = search_res_for_device(rctx);
112       release_msgs(jcr);              /* release queued messages */
113       unlock_reservations();
114       if (stat == 1) {
115          DCR *new_dcr = jcr->read_dcr;
116          dev->unblock();
117          detach_dcr_from_dev(dcr);    /* release old device */
118          /* Copy important info from the new dcr */
119          dev = dcr->dev = new_dcr->dev; 
120          jcr->read_dcr = dcr; 
121          dcr->device = new_dcr->device;
122          dcr->max_job_spool_size = dcr->device->max_job_spool_size;
123          attach_dcr_to_dev(dcr);
124          new_dcr->VolumeName[0] = 0;
125          free_dcr(new_dcr);
126          dev->block(BST_DOING_ACQUIRE); 
127          Jmsg(jcr, M_INFO, 0, _("Media Type change.  New device %s chosen.\n"),
128             dev->print_name());
129          bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
130          bstrncpy(dcr->media_type, vol->MediaType, sizeof(dcr->media_type));
131          dcr->VolCatInfo.Slot = vol->Slot;
132          bstrncpy(dcr->pool_name, store->pool_name, sizeof(dcr->pool_name));
133          bstrncpy(dcr->pool_type, store->pool_type, sizeof(dcr->pool_type));
134       } else if (stat == 0) {   /* device busy */
135          Dmsg1(000, "Device %s is busy.\n", vol->device);
136       } else {
137          /* error */
138          Jmsg1(jcr, M_FATAL, 0, _("No suitable device found to read Volume \"%s\"\n"),
139             vol->VolumeName);
140          jcr->dcr = dcr_save;
141          goto get_out;
142       }
143       jcr->dcr = dcr_save;
144    }
145
146
147    init_device_wait_timers(dcr);
148
149    tape_previously_mounted = dev->can_read() || dev->can_append() ||
150                              dev->is_labeled();
151    tape_initially_mounted = tape_previously_mounted;
152
153
154    /* Volume info is always needed because of VolParts */
155    Dmsg0(200, "dir_get_volume_info\n");
156    if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_READ)) {
157       Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
158    }
159    
160    for ( ;; ) {
161       /* If not polling limit retries */
162       if (!dev->poll && retry++ > 10) {
163          break;
164       }
165       dev->clear_labeled();              /* force reread of label */
166       if (job_canceled(jcr)) {
167          Mmsg1(dev->errmsg, _("Job %d canceled.\n"), jcr->JobId);
168          goto get_out;                /* error return */
169       }
170
171       autoload_device(dcr, 0, NULL);
172
173       /*
174        * This code ensures that the device is ready for
175        * reading. If it is a file, it opens it.
176        * If it is a tape, it checks the volume name
177        */
178       Dmsg1(100, "bstored: open vol=%s\n", dcr->VolumeName);
179       if (dev->open(dcr, OPEN_READ_ONLY) < 0) {
180         Jmsg3(jcr, M_WARNING, 0, _("Read open device %s Volume \"%s\" failed: ERR=%s\n"),
181               dev->print_name(), dcr->VolumeName, dev->bstrerror());
182          goto default_path;
183       }
184       Dmsg1(100, "opened dev %s OK\n", dev->print_name());
185       
186       /* Read Volume Label */
187       
188       Dmsg0(200, "calling read-vol-label\n");
189       vol_label_status = read_dev_volume_label(dcr);
190       switch (vol_label_status) {
191       case VOL_OK:
192          ok = true;
193          memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
194          break;                    /* got it */
195       case VOL_IO_ERROR:
196          /*
197           * Send error message generated by read_dev_volume_label()
198           *  only we really had a tape mounted. This supresses superfluous
199           *  error messages when nothing is mounted.
200           */
201          if (tape_previously_mounted) {
202             Jmsg(jcr, M_WARNING, 0, "%s", jcr->errmsg);
203          }
204          goto default_path;
205       case VOL_NAME_ERROR:
206          if (tape_initially_mounted) {
207             tape_initially_mounted = false;
208             goto default_path;
209          }
210          /* If polling and got a previous bad name, ignore it */
211          if (dev->poll && strcmp(dev->BadVolName, dev->VolHdr.VolumeName) == 0) {
212             goto default_path;
213          } else {
214              bstrncpy(dev->BadVolName, dev->VolHdr.VolumeName, sizeof(dev->BadVolName));
215          }
216          /* Fall through */
217       default:
218          Jmsg1(jcr, M_WARNING, 0, "%s", jcr->errmsg);
219 default_path:
220          tape_previously_mounted = true;
221          
222          /*
223           * If the device requires mount, close it, so the device can be ejected.
224           */
225          if (dev->requires_mount()) {
226             dev->close();
227          }
228          
229          /* Call autochanger only once unless ask_sysop called */
230          if (try_autochanger) {
231             int stat;
232             Dmsg2(200, "calling autoload Vol=%s Slot=%d\n",
233                dcr->VolumeName, dcr->VolCatInfo.Slot);
234             stat = autoload_device(dcr, 0, NULL);
235             if (stat > 0) {
236                try_autochanger = false;
237                continue;              /* try reading volume mounted */
238             }
239          }
240          
241          /* Mount a specific volume and no other */
242          Dmsg0(200, "calling dir_ask_sysop\n");
243          if (!dir_ask_sysop_to_mount_volume(dcr)) {
244             goto get_out;             /* error return */
245          }
246          try_autochanger = true;      /* permit using autochanger again */
247          continue;                    /* try reading again */
248       } /* end switch */
249       break;
250    } /* end for loop */
251    if (!ok) {
252       Jmsg1(jcr, M_FATAL, 0, _("Too many errors trying to mount device %s.\n"),
253             dev->print_name());
254       goto get_out;
255    }
256
257    dev->clear_append();
258    dev->set_read();
259    set_jcr_job_status(jcr, JS_Running);
260    dir_send_job_status(jcr);
261    Jmsg(jcr, M_INFO, 0, _("Ready to read from volume \"%s\" on device %s.\n"),
262       dcr->VolumeName, dev->print_name());
263
264 get_out:
265    P(dev->mutex);
266    if (dcr->reserved_device) {
267       dev->reserved_device--;
268       Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
269       dcr->reserved_device = false;
270    }
271    V(dev->mutex);
272    dev->unblock();
273    Dmsg1(50, "jcr->dcr=%p\n", jcr->dcr);
274    return ok;
275 }
276
277
278 /*
279  * Acquire device for writing. We permit multiple writers.
280  *  If this is the first one, we read the label.
281  *
282  *  Returns: NULL if failed for any reason
283  *           dcr if successful.
284  *   Note, normally reserve_device_for_append() is called
285  *   before this routine.
286  */
287 DCR *acquire_device_for_append(DCR *dcr)
288 {
289    bool release = false;
290    bool recycle = false;
291    bool do_mount = false;
292    DEVICE *dev = dcr->dev;
293    JCR *jcr = dcr->jcr;
294
295    init_device_wait_timers(dcr);
296
297    dev->block(BST_DOING_ACQUIRE);
298    Dmsg1(190, "acquire_append device is %s\n", dev->is_tape()?"tape":
299         (dev->is_dvd()?"DVD":"disk"));
300
301    /*
302     * With the reservation system, this should not happen
303     */
304    if (dev->can_read()) {
305       Jmsg1(jcr, M_FATAL, 0, _("Device %s is busy reading.\n"), dev->print_name());
306       Dmsg1(200, "Device %s is busy reading.\n", dev->print_name());
307       goto get_out;
308    }
309
310    if (dev->can_append()) {
311       Dmsg0(190, "device already in append.\n");
312       /*
313        * Device already in append mode
314        *
315        * Check if we have the right Volume mounted
316        *   OK if current volume info OK
317        *   OK if next volume matches current volume
318        *   otherwise mount desired volume obtained from
319        *    dir_find_next_appendable_volume
320        *  dev->VolHdr.VolumeName is what is in the drive
321        *  dcr->VolumeName is what we pass into the routines, or
322        *    get back from the subroutines.
323        */
324       bstrncpy(dcr->VolumeName, dev->VolHdr.VolumeName, sizeof(dcr->VolumeName));
325       if (!dir_get_volume_info(dcr, GET_VOL_INFO_FOR_WRITE) &&
326           !(dir_find_next_appendable_volume(dcr) &&
327             strcmp(dev->VolHdr.VolumeName, dcr->VolumeName) == 0)) { /* wrong tape mounted */
328          Dmsg2(190, "Wrong tape mounted: %s. wants:%s\n", dev->VolHdr.VolumeName,
329             dcr->VolumeName);
330          /* Release volume reserved by dir_find_next_appendable_volume() */
331          if (dcr->VolumeName[0]) {
332             free_unused_volume(dcr);
333          }
334          if (dev->num_writers != 0) {
335             Jmsg3(jcr, M_FATAL, 0, _("Wanted Volume \"%s\", but device %s is busy writing on \"%s\" .\n"), 
336                  dcr->VolumeName, dev->print_name(), dev->VolHdr.VolumeName);
337             Dmsg3(200, "Wanted Volume \"%s\", but device %s is busy writing on \"%s\" .\n",  
338                  dcr->VolumeName, dev->print_name(), dev->VolHdr.VolumeName);
339             goto get_out;
340          }
341          /* Wrong tape mounted, release it, then fall through to get correct one */
342          Dmsg0(190, "Wrong tape mounted, release and try mount.\n");
343          release = true;
344          do_mount = true;
345       } else {
346          /*
347           * At this point, the correct tape is already mounted, so
348           *   we do not need to do mount_next_write_volume(), unless
349           *   we need to recycle the tape.
350           */
351           recycle = strcmp(dcr->VolCatInfo.VolCatStatus, "Recycle") == 0;
352           Dmsg1(190, "Correct tape mounted. recycle=%d\n", recycle);
353           if (recycle && dev->num_writers != 0) {
354              Jmsg(jcr, M_FATAL, 0, _("Cannot recycle volume \"%s\""
355                   " on device %s because it is in use by another job.\n"),
356                   dev->VolHdr.VolumeName, dev->print_name());
357              goto get_out;
358           }
359           if (dev->num_writers == 0) {
360              memcpy(&dev->VolCatInfo, &dcr->VolCatInfo, sizeof(dev->VolCatInfo));
361           }
362       }
363    } else {
364       /* Not already in append mode, so mount the device */
365       Dmsg0(190, "Not in append mode, try mount.\n");
366       ASSERT(dev->num_writers == 0);
367       do_mount = true;
368    }
369
370    if (do_mount || recycle) {
371       Dmsg0(190, "Do mount_next_write_vol\n");
372       bool mounted = mount_next_write_volume(dcr, release);
373       if (!mounted) {
374          if (!job_canceled(jcr)) {
375             /* Reduce "noise" -- don't print if job canceled */
376             Jmsg(jcr, M_FATAL, 0, _("Could not ready device %s for append.\n"),
377                dev->print_name());
378             Dmsg1(200, "Could not ready device %s for append.\n", 
379                dev->print_name());
380          }
381          goto get_out;
382       }
383       Dmsg2(190, "Output pos=%u:%u\n", dcr->dev->file, dcr->dev->block_num);
384    }
385
386    dev->num_writers++;                /* we are now a writer */
387    if (jcr->NumVolumes == 0) {
388       jcr->NumVolumes = 1;
389    }
390    P(dev->mutex);
391    if (dcr->reserved_device) {
392       dev->reserved_device--;
393       Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
394       dcr->reserved_device = false;
395    }
396    V(dev->mutex);
397    dev->unblock();
398    return dcr;
399
400 /*
401  * Error return
402  */
403 get_out:
404    P(dev->mutex);
405    if (dcr->reserved_device) {
406       dev->reserved_device--;
407       Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
408       dcr->reserved_device = false;
409    }
410    V(dev->mutex);
411    dev->unblock();
412    return NULL;
413 }
414
415
416 /*
417  * This job is done, so release the device. From a Unix standpoint,
418  *  the device remains open.
419  *
420  * Note, if we are spooling, we may enter with the device locked.
421  * However, in all cases, unlock the device when leaving.
422  *
423  */
424 bool release_device(DCR *dcr)
425 {
426    JCR *jcr = dcr->jcr;
427    DEVICE *dev = dcr->dev;
428    bool ok = true;
429
430    /* lock only if not already locked by this thread */
431    if (!dcr->dev_locked) {
432       lock_device(dev);
433    }
434    Dmsg2(100, "release_device device %s is %s\n", dev->print_name(), dev->is_tape()?"tape":"disk");
435
436    /* if device is reserved, job never started, so release the reserve here */
437    if (dcr->reserved_device) {
438       dev->reserved_device--;
439       Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
440       dcr->reserved_device = false;
441    }
442
443    if (dev->can_read()) {
444       dev->clear_read();              /* clear read bit */
445
446       /******FIXME**** send read volume usage statistics to director */
447
448    } else if (dev->num_writers > 0) {
449       /* 
450        * Note if WEOT is set, we are at the end of the tape
451        *   and may not be positioned correctly, so the
452        *   job_media_record and update_vol_info have already been
453        *   done, which means we skip them here.
454        */
455       dev->num_writers--;
456       Dmsg1(100, "There are %d writers in release_device\n", dev->num_writers);
457       if (dev->is_labeled()) {
458          Dmsg0(100, "dir_create_jobmedia_record. Release\n");
459          if (!dev->at_weot() && !dir_create_jobmedia_record(dcr)) {
460             Jmsg(jcr, M_FATAL, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
461                dcr->VolCatInfo.VolCatName, jcr->Job);
462          }
463          /* If no more writers, write an EOF */
464          if (!dev->num_writers && dev->can_write()) {
465             dev->weof(1);
466             write_ansi_ibm_labels(dcr, ANSI_EOF_LABEL, dev->VolHdr.VolumeName);
467          }
468          if (!dev->at_weot()) {
469             dev->VolCatInfo.VolCatFiles = dev->file;   /* set number of files */
470             dev->VolCatInfo.VolCatJobs++;              /* increment number of jobs */
471             /* Note! do volume update before close, which zaps VolCatInfo */
472             Dmsg0(100, "dir_update_vol_info. Release0\n");
473             dir_update_volume_info(dcr, false); /* send Volume info to Director */
474          }
475       }
476
477    } else {
478       /*                
479        * If we reach here, it is most likely because the job
480        *   has failed, since the device is not in read mode and
481        *   there are no writers. It was probably reserved.
482        */
483    }
484
485    /* If no writers, close if file or !CAP_ALWAYS_OPEN */
486    if (dev->num_writers == 0 && (!dev->is_tape() || !dev_cap(dev, CAP_ALWAYSOPEN))) {
487       dvd_remove_empty_part(dcr);        /* get rid of any empty spool part */
488       dev->close();
489    }
490
491    /* Fire off Alert command and include any output */
492    if (!job_canceled(jcr) && dcr->device->alert_command) {
493       POOLMEM *alert;
494       int status = 1;
495       BPIPE *bpipe;
496       char line[MAXSTRING];
497       alert = get_pool_memory(PM_FNAME);
498       alert = edit_device_codes(dcr, alert, dcr->device->alert_command, "");
499       bpipe = open_bpipe(alert, 0, "r");
500       if (bpipe) {
501          while (fgets(line, sizeof(line), bpipe->rfd)) {
502             Jmsg(jcr, M_ALERT, 0, _("Alert: %s"), line);
503          }
504          status = close_bpipe(bpipe);
505       } else {
506          status = errno;
507       }
508       if (status != 0) {
509          berrno be;
510          Jmsg(jcr, M_ALERT, 0, _("3997 Bad alert command: %s: ERR=%s.\n"),
511               alert, be.strerror(status));
512       }
513
514       Dmsg1(400, "alert status=%d\n", status);
515       free_pool_memory(alert);
516    }
517    dcr->dev_locked = false;              /* set no longer locked */
518    unlock_device(dev);
519    if (jcr->read_dcr == dcr) {
520       jcr->read_dcr = NULL;
521    }
522    if (jcr->dcr == dcr) {
523       jcr->dcr = NULL;
524    }
525    free_dcr(dcr);
526    return ok;
527 }
528
529 /*
530  * Create a new Device Control Record and attach
531  *   it to the device (if this is a real job).
532  */
533 DCR *new_dcr(JCR *jcr, DEVICE *dev)
534 {
535    DCR *dcr = (DCR *)malloc(sizeof(DCR));
536    memset(dcr, 0, sizeof(DCR));
537    dcr->jcr = jcr;
538    if (dev) {
539       dcr->dev = dev;
540       dcr->device = dev->device;
541       dcr->block = new_block(dev);
542       dcr->rec = new_record();
543       dcr->max_job_spool_size = dev->device->max_job_spool_size;
544       attach_dcr_to_dev(dcr);
545    }
546    dcr->spool_fd = -1;
547    return dcr;
548 }
549
550 /*
551  * Search the dcrs list for the given dcr. If it is found,
552  *  as it should be, then remove it. Also zap the jcr pointer
553  *  to the dcr if it is the same one.
554  */
555 #ifdef needed
556 static void remove_dcr_from_dcrs(DCR *dcr)
557 {
558    JCR *jcr = dcr->jcr;
559    if (jcr->dcrs) {
560       int i = 0;
561       DCR *ldcr;
562       int num = jcr->dcrs->size();
563       for (i=0; i < num; i++) {
564          ldcr = (DCR *)jcr->dcrs->get(i);
565          if (ldcr == dcr) {
566             jcr->dcrs->remove(i);
567             if (jcr->dcr == dcr) {
568                jcr->dcr = NULL;
569             }
570          }
571       }
572    }
573 }
574 #endif
575
576 static void attach_dcr_to_dev(DCR *dcr)
577 {
578    DEVICE *dev = dcr->dev;
579    JCR *jcr = dcr->jcr;
580
581    if (!dcr->attached_to_dev && dev->is_open() && jcr && jcr->JobType != JT_SYSTEM) {
582       dev->attached_dcrs->append(dcr);  /* attach dcr to device */
583       dcr->attached_to_dev = true;
584    }
585 }
586
587 void detach_dcr_from_dev(DCR *dcr)
588 {
589    DEVICE *dev = dcr->dev;
590
591    if (dcr->reserved_device) {
592       dcr->reserved_device = false;
593       lock_device(dev);
594       dev->reserved_device--;
595       Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
596       dcr->reserved_device = false;
597       /* If we set read mode in reserving, remove it */
598       if (dev->can_read()) {
599          dev->clear_read();
600       }
601       if (dev->num_writers < 0) {
602          Jmsg1(dcr->jcr, M_ERROR, 0, _("Hey! num_writers=%d!!!!\n"), dev->num_writers);
603          dev->num_writers = 0;
604       }
605       unlock_device(dev);
606    }
607
608    /* Detach this dcr only if attached */
609    if (dcr->attached_to_dev) {
610       dcr->dev->attached_dcrs->remove(dcr);  /* detach dcr from device */
611       dcr->attached_to_dev = false;
612 //    remove_dcr_from_dcrs(dcr);      /* remove dcr from jcr list */
613    }
614    free_unused_volume(dcr);           /* free unused vols attached to this dcr */
615    pthread_cond_broadcast(&dcr->dev->wait_next_vol);
616    pthread_cond_broadcast(&wait_device_release);
617 }
618
619 /*
620  * Free up all aspects of the given dcr -- i.e. dechain it,
621  *  release allocated memory, zap pointers, ...
622  */
623 void free_dcr(DCR *dcr)
624 {
625
626    detach_dcr_from_dev(dcr);
627
628    if (dcr->block) {
629       free_block(dcr->block);
630    }
631    if (dcr->rec) {
632       free_record(dcr->rec);
633    }
634    if (dcr->jcr) {
635       dcr->jcr->dcr = NULL;
636    }
637    free(dcr);
638 }