]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/reserve.c
kes I reworked the OpenSSL include/lib flags to be handled in
[bacula/bacula] / bacula / src / stored / reserve.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2007 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 plus additions
11    that are listed 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 John Walker.
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  *   Drive reservation functions for Storage Daemon
30  *
31  *   Kern Sibbald, MM
32  *
33  *   Split from job.c and acquire.c June 2005
34  *
35  *   Version $Id$
36  *
37  */
38
39 #include "bacula.h"
40 #include "stored.h"
41
42 static dlist *vol_list = NULL;
43 static pthread_mutex_t vol_list_lock = PTHREAD_MUTEX_INITIALIZER;
44
45 /* Forward referenced functions */
46 static int can_reserve_drive(DCR *dcr, RCTX &rctx);
47 static int reserve_device(RCTX &rctx);
48 static bool reserve_device_for_read(DCR *dcr);
49 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx);
50 static bool use_storage_cmd(JCR *jcr);
51 static void queue_reserve_message(JCR *jcr);
52
53 /* Requests from the Director daemon */
54 static char use_storage[]  = "use storage=%127s media_type=%127s "
55    "pool_name=%127s pool_type=%127s append=%d copy=%d stripe=%d\n";
56 static char use_device[]  = "use device=%127s\n";
57
58 /* Responses sent to Director daemon */
59 static char OK_device[] = "3000 OK use device device=%s\n";
60 static char NO_device[] = "3924 Device \"%s\" not in SD Device resources.\n";
61 static char BAD_use[]   = "3913 Bad use command: %s\n";
62
63 bool use_cmd(JCR *jcr) 
64 {
65    /*
66     * Get the device, media, and pool information
67     */
68    if (!use_storage_cmd(jcr)) {
69       set_jcr_job_status(jcr, JS_ErrorTerminated);
70       memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
71       return false;
72    }
73    return true;
74 }
75
76 static int my_compare(void *item1, void *item2)
77 {
78    return strcmp(((VOLRES *)item1)->vol_name, ((VOLRES *)item2)->vol_name);
79 }
80
81 static brwlock_t reservation_lock;
82
83 void init_reservations_lock()
84 {
85    int errstat;
86    if ((errstat=rwl_init(&reservation_lock)) != 0) {
87       berrno be;
88       Emsg1(M_ABORT, 0, _("Unable to initialize reservation lock. ERR=%s\n"),
89             be.bstrerror(errstat));
90    }
91
92 }
93
94 void term_reservations_lock()
95 {
96    rwl_destroy(&reservation_lock);
97 }
98
99 int reservations_lock_count = 0;
100
101 /* This applies to a drive and to Volumes */
102 void _lock_reservations()
103 {
104    int errstat;
105    reservations_lock_count++;
106    if ((errstat=rwl_writelock(&reservation_lock)) != 0) {
107       berrno be;
108       Emsg2(M_ABORT, 0, "rwl_writelock failure. stat=%d: ERR=%s\n",
109            errstat, be.bstrerror(errstat));
110    }
111 }
112
113 void _unlock_reservations()
114 {
115    int errstat;
116    reservations_lock_count--;
117    if ((errstat=rwl_writeunlock(&reservation_lock)) != 0) {
118       berrno be;
119       Emsg2(M_ABORT, 0, "rwl_writeunlock failure. stat=%d: ERR=%s\n",
120            errstat, be.bstrerror(errstat));
121    }
122 }
123
124 /*
125  * List Volumes -- this should be moved to status.c
126  */
127 enum {
128    debug_lock = true,
129    debug_nolock = false
130 };
131
132 static void debug_list_volumes(const char *imsg, bool do_lock)
133 {
134    VOLRES *vol;
135    POOL_MEM msg(PM_MESSAGE);
136    int count = 0;
137    DEVICE *dev = NULL;
138
139    if (do_lock) P(vol_list_lock);
140    for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
141       if (vol->dev) {
142          Mmsg(msg, "List from %s: %s at %p on device %s\n", imsg, 
143               vol->vol_name, vol->vol_name, vol->dev->print_name());
144       } else {
145          Mmsg(msg, "List from %s: %s at %p no dev\n", imsg, vol->vol_name, vol->vol_name);
146       }
147       Dmsg1(100, "%s", msg.c_str());
148       count++;
149    }
150
151    for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
152       if (vol->dev == dev) {
153          Dmsg0(000, "Two Volumes on same device.\n");
154          ASSERT(0);
155          dev = vol->dev;
156       }
157    }
158
159    Dmsg2(100, "List from %s: %d volumes\n", imsg, count);
160    if (do_lock) V(vol_list_lock);
161 }
162
163
164 /*
165  * List Volumes -- this should be moved to status.c
166  */
167 void list_volumes(void sendit(const char *msg, int len, void *sarg), void *arg)
168 {
169    VOLRES *vol;
170    POOL_MEM msg(PM_MESSAGE);
171    int len;
172
173    P(vol_list_lock);
174    for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
175       if (vol->dev) {
176          len = Mmsg(msg, "%s on device %s\n", vol->vol_name, vol->dev->print_name());
177          sendit(msg.c_str(), len, arg);
178       } else {
179          len = Mmsg(msg, "%s no dev\n", vol->vol_name);
180          sendit(msg.c_str(), len, arg);
181       }
182    }
183    V(vol_list_lock);
184 }
185
186 /*
187  * Create a Volume item to put in the Volume list
188  *   Ensure that the device points to it.
189  */
190 static VOLRES *new_vol_item(DCR *dcr, const char *VolumeName)
191 {
192    VOLRES *vol;
193    vol = (VOLRES *)malloc(sizeof(VOLRES));
194    memset(vol, 0, sizeof(VOLRES));
195    vol->vol_name = bstrdup(VolumeName);
196    vol->dev = dcr->dev;
197    Dmsg4(100, "New Vol=%s at %p dev=%s JobId=%u\n", VolumeName, vol->vol_name,
198          vol->dev->print_name(), (int)dcr->jcr->JobId);
199    return vol;
200 }
201
202 static void free_vol_item(VOLRES *vol)
203 {
204    free(vol->vol_name);
205    if (vol->dev) {
206       vol->dev->vol = NULL;
207    }
208    free(vol);
209 }
210
211
212 /*
213  * Put a new Volume entry in the Volume list. This
214  *  effectively reserves the volume so that it will
215  *  not be mounted again.
216  *
217  * If the device has any current volume associated with it,
218  *  and it is a different Volume, and the device is not busy,
219  *  we release the old Volume item and insert the new one.
220  * 
221  * It is assumed that the device is free and locked so that
222  *  we can change the device structure.
223  *
224  * Some details of the Volume list handling:
225  *
226  *  1. The Volume list entry must be attached to the drive (rather than 
227  *       attached to a job as it currently is. I.e. the drive that "owns" 
228  *       the volume (reserved, in use, mounted)
229  *       must point to the volume (still to be maintained in a list).
230  *
231  *  2. The Volume is entered in the list when a drive is reserved.  
232  *
233  *  3. When a drive is in use, the device code must appropriately update the
234  *      volume name as it changes (currently the list is static -- an entry is
235  *      removed when the Volume is no longer reserved, in use or mounted).  
236  *      The new code must keep the same list entry as long as the drive
237  *       has any volume associated with it but the volume name in the list
238  *       must be updated when the drive has a different volume mounted.
239  *
240  *  4. A job that has reserved a volume, can un-reserve the volume, and if the 
241  *      volume is not mounted, and not reserved, and not in use, it will be
242  *      removed from the list.
243  *
244  *  5. If a job wants to reserve a drive with a different Volume from the one on
245  *      the drive, it can re-use the drive for the new Volume.
246  *
247  *  6. If a job wants a Volume that is in a different drive, it can either use the
248  *      other drive or take the volume, only if the other drive is not in use or
249  *      not reserved.
250  *
251  *  One nice aspect of this is that the reserve use count and the writer use count 
252  *  already exist and are correctly programmed and will need no changes -- use 
253  *  counts are always very tricky.
254  *
255  *  The old code had a concept of "reserving" a Volume, but it needs to be changed 
256  *  to reserving and using a drive.  A volume is must be attached to (owned by) a 
257  *  drive and can move from drive to drive or be unused given certain specific 
258  *  conditions of the drive.  The key is that the drive must "own" the Volume.  
259  *  The old code has the job (dcr) owning the volume (more or less).  The job is 
260  *  to change the insertion and removal of the volumes from the list to be based 
261  *  on the drive rather than the job.  
262  *
263  *  Return: VOLRES entry on success
264  *          NULL volume busy on another drive
265  */
266 VOLRES *reserve_volume(DCR *dcr, const char *VolumeName)
267 {
268    VOLRES *vol, *nvol;
269    DEVICE *dev = dcr->dev;
270
271    ASSERT(dev != NULL);
272
273    Dmsg1(100, "reserve_volume %s\n", VolumeName);
274    /* 
275     * We lock the reservations system here to ensure
276     *  when adding a new volume that no newly scheduled
277     *  job can reserve it.
278     */
279    P(vol_list_lock);
280    debug_list_volumes("begin reserve_volume", debug_nolock);
281    /* 
282     * First, remove any old volume attached to this device as it
283     *  is no longer used.
284     */
285    if (dev->vol) {
286       vol = dev->vol;
287       /*
288        * Make sure we don't remove the current volume we are inserting
289        *  because it was probably inserted by another job.
290        */
291       if (strcmp(vol->vol_name, VolumeName) == 0) {
292          goto get_out;                  /* Volume already on this device */
293       } else {
294          Dmsg3(100, "reserve_vol free vol=%s at %p JobId=%u\n", vol->vol_name,
295                vol->vol_name, (int)dcr->jcr->JobId);
296          debug_list_volumes("reserve_vol free", debug_nolock);
297          vol_list->remove(vol);
298          free_vol_item(vol);
299       }
300    }
301
302    /* Create a new Volume entry */
303    nvol = new_vol_item(dcr, VolumeName);
304
305    /*
306     * Now try to insert the new Volume
307     */
308    vol = (VOLRES *)vol_list->binary_insert(nvol, my_compare);
309    if (vol != nvol) {
310       Dmsg2(100, "Found vol=%s dev-same=%d\n", vol->vol_name, dev==vol->dev);
311       /*
312        * At this point, a Volume with this name already is in the list,
313        *   so we simply release our new Volume entry. Note, this should
314        *   only happen if we are moving the volume from one drive to another.
315        */
316       Dmsg3(100, "reserve_vol free-tmp vol=%s at %p JobId=%u\n", vol->vol_name,
317             vol->vol_name, (int)dcr->jcr->JobId);
318       /*
319        * Clear dev pointer so that free_vol_item() doesn't 
320        *  take away our volume. 
321        */
322       nvol->dev = NULL;                   /* don't zap dev entry */
323       free_vol_item(nvol);
324
325       /* Check if we are trying to use the Volume on a different drive */
326       if (dev != vol->dev) {
327          /* Caller wants to switch Volume to another device */
328          if (!vol->dev->is_busy()) {
329             /* OK to move it -- I'm not sure this will work */
330             Dmsg3(100, "==== Swap vol=%s from dev=%s to %s\n", VolumeName,
331                vol->dev->print_name(), dev->print_name());
332             vol->dev->vol = NULL;         /* take vol from old drive */
333             vol->dev->VolHdr.VolumeName[0] = 0;
334             vol->dev = dev;               /* point vol at new drive */
335             dev->vol = vol;               /* point dev at vol */
336             dev->VolHdr.VolumeName[0] = 0;
337          } else {
338             Dmsg3(100, "Volume busy could not swap vol=%s from dev=%s to %s\n", VolumeName,
339                vol->dev->print_name(), dev->print_name());
340             vol = NULL;                /* device busy */
341          }
342       }
343    }
344    dev->vol = vol;
345
346 get_out:
347    debug_list_volumes("end new volume", debug_nolock);
348    V(vol_list_lock);
349    return vol;
350 }
351
352 /*
353  * Search for a Volume name in the Volume list.
354  *
355  *  Returns: VOLRES entry on success
356  *           NULL if the Volume is not in the list
357  */
358 VOLRES *find_volume(const char *VolumeName)
359 {
360    VOLRES vol, *fvol;
361    /* Do not lock reservations here */
362    P(vol_list_lock);
363    vol.vol_name = bstrdup(VolumeName);
364    fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
365    free(vol.vol_name);
366    Dmsg2(100, "find_vol=%s found=%d\n", VolumeName, fvol!=NULL);
367    debug_list_volumes("find_volume", debug_nolock);
368    V(vol_list_lock);
369    return fvol;
370 }
371
372 /* 
373  * Remove any reservation from a drive and tell the system
374  *  that the volume is unused at least by us.
375  */
376 void unreserve_device(DCR *dcr)
377 {
378    DEVICE *dev = dcr->dev;
379    dev->dlock();
380    if (dcr->reserved_device) {
381       dcr->reserved_device = false;
382       dev->reserved_device--;
383       Dmsg2(100, "Dec reserve=%d dev=%s\n", dev->reserved_device, dev->print_name());
384       dcr->reserved_device = false;
385       /* If we set read mode in reserving, remove it */
386       if (dev->can_read()) {
387          dev->clear_read();
388       }
389       if (dev->num_writers < 0) {
390          Jmsg1(dcr->jcr, M_ERROR, 0, _("Hey! num_writers=%d!!!!\n"), dev->num_writers);
391          dev->num_writers = 0;
392       }
393    }
394
395    volume_unused(dcr);
396    dev->dunlock();
397 }
398
399 /*  
400  * Free a Volume from the Volume list if it is no longer used
401  *
402  *  Returns: true if the Volume found and removed from the list
403  *           false if the Volume is not in the list or is in use
404  */
405 bool volume_unused(DCR *dcr)
406 {
407    DEVICE *dev = dcr->dev;
408
409    if (dev->vol == NULL) {
410       Dmsg1(100, " unreserve_volume: no vol on %s\n", dev->print_name());
411       debug_list_volumes("null return unreserve_volume", debug_lock);
412       return false;
413    }
414
415    if (dev->is_busy()) {
416       Dmsg1(100, "unreserve_volume: dev is busy %s\n", dev->print_name());
417       debug_list_volumes("dev busy return unreserve_volume", debug_lock);
418       return false;
419    }
420
421    return free_volume(dev);
422 }
423
424 /*
425  * Unconditionally release the volume
426  */
427 bool free_volume(DEVICE *dev)
428 {
429    VOLRES *vol;
430
431    if (dev->vol == NULL) {
432       Dmsg1(100, "No vol on dev %s\n", dev->print_name());
433       return false;
434    }
435    P(vol_list_lock);
436    vol = dev->vol;
437    dev->vol = NULL;
438    Dmsg1(100, "free_volume %s\n", vol->vol_name);
439    vol_list->remove(vol);
440    Dmsg3(100, "free_volume %s at %p dev=%s\n", vol->vol_name, vol->vol_name,
441          dev->print_name());
442    free_vol_item(vol);
443    debug_list_volumes("free_volume", debug_nolock);
444    V(vol_list_lock);
445    return vol != NULL;
446 }
447
448       
449 /* Create the Volume list */
450 void create_volume_list()
451 {
452    VOLRES *dummy = NULL;
453    if (vol_list == NULL) {
454       vol_list = New(dlist(dummy, &dummy->link));
455    }
456 }
457
458 /* Release all Volumes from the list */
459 void free_volume_list()
460 {
461    VOLRES *vol;
462    if (!vol_list) {
463       return;
464    }
465    P(vol_list_lock);
466    for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
467       Dmsg2(100, "Unreleased Volume=%s dev=%p\n", vol->vol_name, vol->dev);
468       free(vol->vol_name);
469       vol->vol_name = NULL;
470    }
471    delete vol_list;
472    vol_list = NULL;
473    V(vol_list_lock);
474 }
475
476 bool is_volume_in_use(DCR *dcr)
477 {
478    VOLRES *vol = find_volume(dcr->VolumeName);
479    if (!vol) {
480       Dmsg1(100, "Vol=%s not in use.\n", dcr->VolumeName);
481       return false;                   /* vol not in list */
482    }
483    ASSERT(vol->dev != NULL);
484
485    if (dcr->dev == vol->dev) {        /* same device OK */
486       Dmsg1(100, "Vol=%s on same dev.\n", dcr->VolumeName);
487       return false;
488    }
489    if (!vol->dev->is_busy()) {
490       Dmsg2(100, "Vol=%s dev=%s not busy.\n", dcr->VolumeName, vol->dev->print_name());
491       return false;
492    }
493    Dmsg2(100, "Vol=%s used by %s.\n", dcr->VolumeName, vol->dev->print_name());
494    return true;
495 }
496
497
498 /*
499  * We get the following type of information:
500  *
501  * use storage=xxx media_type=yyy pool_name=xxx pool_type=yyy append=1 copy=0 strip=0
502  *  use device=zzz
503  *  use device=aaa
504  *  use device=bbb
505  * use storage=xxx media_type=yyy pool_name=xxx pool_type=yyy append=0 copy=0 strip=0
506  *  use device=bbb
507  *
508  */
509 static bool use_storage_cmd(JCR *jcr)
510 {
511    POOL_MEM store_name, dev_name, media_type, pool_name, pool_type;
512    BSOCK *dir = jcr->dir_bsock;
513    int append;
514    bool ok;       
515    int Copy, Stripe;
516    DIRSTORE *store;
517    RCTX rctx;
518    char *msg;
519    alist *msgs;
520    alist *dirstore;
521
522    memset(&rctx, 0, sizeof(RCTX));
523    rctx.jcr = jcr;
524    /*
525     * If there are multiple devices, the director sends us
526     *   use_device for each device that it wants to use.
527     */
528    dirstore = New(alist(10, not_owned_by_alist));
529 // Dmsg2(000, "dirstore=%p JobId=%u\n", dirstore, jcr->JobId);
530    msgs = jcr->reserve_msgs = New(alist(10, not_owned_by_alist));  
531    do {
532       Dmsg1(100, "<dird: %s", dir->msg);
533       ok = sscanf(dir->msg, use_storage, store_name.c_str(), 
534                   media_type.c_str(), pool_name.c_str(), 
535                   pool_type.c_str(), &append, &Copy, &Stripe) == 7;
536       if (!ok) {
537          break;
538       }
539       if (append) {
540          jcr->write_store = dirstore;
541       } else {
542          jcr->read_store = dirstore;
543       }
544       rctx.append = append;
545       unbash_spaces(store_name);
546       unbash_spaces(media_type);
547       unbash_spaces(pool_name);
548       unbash_spaces(pool_type);
549       store = new DIRSTORE;
550       dirstore->append(store);
551       memset(store, 0, sizeof(DIRSTORE));
552       store->device = New(alist(10));
553       bstrncpy(store->name, store_name, sizeof(store->name));
554       bstrncpy(store->media_type, media_type, sizeof(store->media_type));
555       bstrncpy(store->pool_name, pool_name, sizeof(store->pool_name));
556       bstrncpy(store->pool_type, pool_type, sizeof(store->pool_type));
557       store->append = append;
558
559       /* Now get all devices */
560       while (dir->recv() >= 0) {
561          Dmsg1(100, "<dird device: %s", dir->msg);
562          ok = sscanf(dir->msg, use_device, dev_name.c_str()) == 1;
563          if (!ok) {
564             break;
565          }
566          unbash_spaces(dev_name);
567          store->device->append(bstrdup(dev_name.c_str()));
568       }
569    }  while (ok && dir->recv() >= 0);
570
571 #ifdef DEVELOPER
572    /* This loop is debug code and can be removed */
573    /* ***FIXME**** remove after 1.38 release */
574    char *device_name;
575    foreach_alist(store, dirstore) {
576       Dmsg6(110, "JobId=%u Storage=%s media_type=%s pool=%s pool_type=%s append=%d\n", 
577          (int)rctx.jcr->JobId,
578          store->name, store->media_type, store->pool_name, 
579          store->pool_type, store->append);
580       foreach_alist(device_name, store->device) {
581          Dmsg1(110, "   Device=%s\n", device_name);
582       }
583    }
584 #endif
585
586    init_jcr_device_wait_timers(jcr);
587    /*                    
588     * At this point, we have a list of all the Director's Storage
589     *  resources indicated for this Job, which include Pool, PoolType,
590     *  storage name, and Media type.     
591     * Then for each of the Storage resources, we have a list of
592     *  device names that were given.
593     *
594     * Wiffle through them and find one that can do the backup.
595     */
596    if (ok) {
597       int retries = 0;                /* wait for device retries */
598       bool fail = false;
599       rctx.notify_dir = true;
600       lock_reservations();
601       for ( ; !fail && !job_canceled(jcr); ) {
602          while ((msg = (char *)msgs->pop())) {
603             free(msg);
604          }
605          rctx.suitable_device = false;
606          rctx.have_volume = false;
607          rctx.VolumeName[0] = 0;
608          rctx.any_drive = false;
609          if (!jcr->PreferMountedVols) {
610             /* Look for unused drives in autochangers */
611             rctx.num_writers = 20000000;   /* start with impossible number */
612             rctx.low_use_drive = NULL;
613             rctx.PreferMountedVols = false;                
614             rctx.exact_match = false;
615             rctx.autochanger_only = true;
616             Dmsg6(110, "JobId=%u PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
617                (int)rctx.jcr->JobId,
618                rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
619                rctx.autochanger_only, rctx.any_drive);
620             if ((ok = find_suitable_device_for_job(jcr, rctx))) {
621                break;
622             }
623             /* Look through all drives possibly for low_use drive */
624             if (rctx.low_use_drive) {
625                rctx.try_low_use_drive = true;
626                if ((ok = find_suitable_device_for_job(jcr, rctx))) {
627                   break;
628                }
629                rctx.try_low_use_drive = false;
630             }
631             rctx.autochanger_only = false;
632             Dmsg6(110, "JobId=%u PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
633                (int)rctx.jcr->JobId,
634                rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
635                rctx.autochanger_only, rctx.any_drive);
636             if ((ok = find_suitable_device_for_job(jcr, rctx))) {
637                break;
638             }
639          }
640          /* Look for an exact match all drives */
641          rctx.PreferMountedVols = true;
642          rctx.exact_match = true;
643          rctx.autochanger_only = false;
644          Dmsg6(110, "JobId=%u PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
645             (int)rctx.jcr->JobId,
646             rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
647             rctx.autochanger_only, rctx.any_drive);
648          if ((ok = find_suitable_device_for_job(jcr, rctx))) {
649             break;
650          }
651          /* Look for any mounted drive */
652          rctx.exact_match = false;
653          Dmsg6(110, "JobId=%u PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
654             (int)rctx.jcr->JobId,
655             rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
656             rctx.autochanger_only, rctx.any_drive);
657          if ((ok = find_suitable_device_for_job(jcr, rctx))) {
658             break;
659          }
660          /* Try any drive */
661          rctx.any_drive = true;
662          Dmsg6(110, "JobId=%u PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
663             (int)rctx.jcr->JobId,
664             rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
665             rctx.autochanger_only, rctx.any_drive);
666          if ((ok = find_suitable_device_for_job(jcr, rctx))) {
667             break;
668          }
669          /* Keep reservations locked *except* during wait_for_device() */
670          unlock_reservations();
671          if (!rctx.suitable_device || !wait_for_device(jcr, retries)) {
672             Dmsg1(100, "JobId=%u Fail. !suitable_device || !wait_for_device\n",
673                  (int)rctx.jcr->JobId);
674             fail = true;
675          }   
676          lock_reservations();
677          bnet_sig(dir, BNET_HEARTBEAT);  /* Inform Dir that we are alive */
678       }
679       unlock_reservations();
680       if (!ok) {
681          /*
682           * If we get here, there are no suitable devices available, which
683           *  means nothing configured.  If a device is suitable but busy
684           *  with another Volume, we will not come here.
685           */
686          unbash_spaces(dir->msg);
687          pm_strcpy(jcr->errmsg, dir->msg);
688          Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
689          Jmsg(jcr, M_FATAL, 0, _("\n"
690             "     Device \"%s\" with MediaType \"%s\" requested by DIR not found in SD Device resources.\n"),
691               dev_name.c_str(), media_type.c_str());
692          bnet_fsend(dir, NO_device, dev_name.c_str());
693
694          Dmsg1(100, ">dird: %s", dir->msg);
695       }
696    } else {
697       unbash_spaces(dir->msg);
698       pm_strcpy(jcr->errmsg, dir->msg);
699       Jmsg(jcr, M_FATAL, 0, _("Failed command: %s\n"), jcr->errmsg);
700       bnet_fsend(dir, BAD_use, jcr->errmsg);
701       Dmsg1(100, ">dird: %s", dir->msg);
702    }
703
704    release_msgs(jcr);
705    return ok;
706 }
707
708 void release_msgs(JCR *jcr)
709 {
710    alist *msgs = jcr->reserve_msgs;
711    char *msg;
712
713    if (!msgs) {
714       return;
715    }
716    lock_reservations();
717    while ((msg = (char *)msgs->pop())) {
718       free(msg);
719    }
720    delete msgs;
721    jcr->reserve_msgs = NULL;
722    unlock_reservations();
723 }
724
725 /*
726  * Search for a device suitable for this job.
727  */
728 bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx)
729 {
730    bool ok;
731    DIRSTORE *store;
732    char *device_name;
733    alist *dirstore;
734
735    if (rctx.append) {
736       dirstore = jcr->write_store;
737    } else {
738       dirstore = jcr->read_store;
739    }
740    /* 
741     * For each storage device that the user specified, we
742     *  search and see if there is a resource for that device.
743     */
744    Dmsg5(110, "JobId=%u PrefMnt=%d exact=%d suitable=%d chgronly=%d\n",
745       (int)rctx.jcr->JobId,
746       rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
747       rctx.autochanger_only);
748    ok = false;
749    foreach_alist(store, dirstore) {
750       rctx.store = store;
751       foreach_alist(device_name, store->device) {
752          int stat;
753          rctx.device_name = device_name;
754          stat = search_res_for_device(rctx); 
755          if (stat == 1) {             /* found available device */
756             Dmsg2(100, "JobId=%u Suitable device found=%s\n", (int)rctx.jcr->JobId, 
757                   device_name);
758             ok = true;
759             break;
760          } else if (stat == 0) {      /* device busy */
761             Dmsg2(110, "JobId=%u Suitable device=%s, busy: not use\n", 
762                   (int)rctx.jcr->JobId, device_name);
763          } else {
764             /* otherwise error */
765             Dmsg1(110, "JobId=%u No suitable device found.\n", (int)rctx.jcr->JobId);
766          }
767       }
768       if (ok) {
769          break;
770       }
771    }
772    return ok;
773 }
774
775 /*
776  * Search for a particular storage device with particular storage
777  *  characteristics (MediaType).
778  */
779 int search_res_for_device(RCTX &rctx) 
780 {
781    AUTOCHANGER *changer;
782    BSOCK *dir = rctx.jcr->dir_bsock;
783    bool ok;
784    int stat;
785
786    Dmsg2(110, "JobId=%u search res for %s\n", (int)rctx.jcr->JobId, rctx.device_name);
787    /* Look through Autochangers first */
788    foreach_res(changer, R_AUTOCHANGER) {
789       Dmsg2(150, "JobId=%u Try match changer res=%s\n", (int)rctx.jcr->JobId, changer->hdr.name);
790       /* Find resource, and make sure we were able to open it */
791       if (fnmatch(rctx.device_name, changer->hdr.name, 0) == 0) {
792          /* Try each device in this AutoChanger */
793          foreach_alist(rctx.device, changer->device) {
794             Dmsg2(110, "JobId=%u Try changer device %s\n", (int)rctx.jcr->JobId, 
795                   rctx.device->hdr.name);
796             stat = reserve_device(rctx);
797             if (stat != 1) {             /* try another device */
798                continue;
799             }
800             POOL_MEM dev_name;
801             if (rctx.store->append == SD_APPEND) {
802                Dmsg3(100, "JobId=%u Device %s reserved=%d for append.\n", 
803                   (int)rctx.jcr->JobId, rctx.device->hdr.name,
804                   rctx.jcr->dcr->dev->reserved_device);
805             } else {
806                Dmsg3(100, "JobId=%u Device %s reserved=%d for read.\n", 
807                   (int)rctx.jcr->JobId, rctx.device->hdr.name,
808                   rctx.jcr->read_dcr->dev->reserved_device);
809             }
810             if (rctx.notify_dir) {
811                pm_strcpy(dev_name, rctx.device->hdr.name);
812                bash_spaces(dev_name);
813                ok = bnet_fsend(dir, OK_device, dev_name.c_str());  /* Return real device name */
814                Dmsg1(100, ">dird changer: %s", dir->msg);
815             } else {
816                ok = true;
817             }
818             return ok ? 1 : -1;
819          }
820       }
821    }
822
823    /* Now if requested look through regular devices */
824    if (!rctx.autochanger_only) {
825       foreach_res(rctx.device, R_DEVICE) {
826          Dmsg2(150, "JobId=%u Try match res=%s\n", (int)rctx.jcr->JobId, rctx.device->hdr.name);
827          /* Find resource, and make sure we were able to open it */
828          if (fnmatch(rctx.device_name, rctx.device->hdr.name, 0) == 0) {
829             stat = reserve_device(rctx);
830             if (stat != 1) {
831                return stat;
832             }
833             if (rctx.notify_dir) {
834                bash_spaces(rctx.device_name);
835                ok = bnet_fsend(dir, OK_device, rctx.device_name);
836                Dmsg1(100, ">dird dev: %s", dir->msg);
837             } else {
838                ok = true;
839             }
840             return ok ? 1 : -1;
841          }
842       }
843    }
844    return -1;                    /* nothing found */
845 }
846
847 /*
848  *  Try to reserve a specific device.
849  *
850  *  Returns: 1 -- OK, have DCR
851  *           0 -- must wait
852  *          -1 -- fatal error
853  */
854 static int reserve_device(RCTX &rctx)
855 {
856    bool ok;
857    DCR *dcr;
858    const int name_len = MAX_NAME_LENGTH;
859
860    /* Make sure MediaType is OK */
861    Dmsg3(110, "JobId=%u MediaType device=%s request=%s\n",
862          (int)rctx.jcr->JobId,
863          rctx.device->media_type, rctx.store->media_type);
864    if (strcmp(rctx.device->media_type, rctx.store->media_type) != 0) {
865       return -1;
866    }
867
868    /* Make sure device exists -- i.e. we can stat() it */
869    if (!rctx.device->dev) {
870       rctx.device->dev = init_dev(rctx.jcr, rctx.device);
871    }
872    if (!rctx.device->dev) {
873       if (rctx.device->changer_res) {
874         Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
875            "     Device \"%s\" in changer \"%s\" requested by DIR could not be opened or does not exist.\n"),
876              rctx.device->hdr.name, rctx.device_name);
877       } else {
878          Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
879             "     Device \"%s\" requested by DIR could not be opened or does not exist.\n"),
880               rctx.device_name);
881       }
882       return -1;  /* no use waiting */
883    }  
884
885    rctx.suitable_device = true;
886    Dmsg2(110, "Try reserve %s JobId=%u\n", rctx.device->hdr.name,
887          rctx.jcr->JobId);
888    dcr = new_dcr(rctx.jcr, rctx.device->dev);
889    if (!dcr) {
890       BSOCK *dir = rctx.jcr->dir_bsock;
891       bnet_fsend(dir, _("3926 Could not get dcr for device: %s\n"), rctx.device_name);
892       Dmsg1(100, ">dird: %s", dir->msg);
893       return -1;
894    }
895    bstrncpy(dcr->pool_name, rctx.store->pool_name, name_len);
896    bstrncpy(dcr->pool_type, rctx.store->pool_type, name_len);
897    bstrncpy(dcr->media_type, rctx.store->media_type, name_len);
898    bstrncpy(dcr->dev_name, rctx.device_name, name_len);
899    if (rctx.store->append == SD_APPEND) {
900       Dmsg3(100, "JobId=%u have_vol=%d vol=%s\n", (int)rctx.jcr->JobId,
901           rctx.have_volume, rctx.VolumeName);                                   
902       if (!rctx.have_volume) {
903          dcr->any_volume = true;
904          if (dir_find_next_appendable_volume(dcr)) {
905             bstrncpy(rctx.VolumeName, dcr->VolumeName, sizeof(rctx.VolumeName));
906             Dmsg2(100, "JobId=%u looking for Volume=%s\n", (int)rctx.jcr->JobId, rctx.VolumeName);
907             rctx.have_volume = true;
908          } else {
909             Dmsg1(100, "JobId=%u No next volume found\n", (int)rctx.jcr->JobId);
910             rctx.have_volume = false;
911             rctx.VolumeName[0] = 0;
912         }
913       }
914       ok = reserve_device_for_append(dcr, rctx);
915       if (ok) {
916          rctx.jcr->dcr = dcr;
917          Dmsg6(100, "JobId=%u Reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
918                (int)rctx.jcr->JobId,
919                dcr->dev->reserved_device,
920                dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
921       }
922    } else {
923       ok = reserve_device_for_read(dcr);
924       if (ok) {
925          rctx.jcr->read_dcr = dcr;
926          Dmsg6(100, "JobId=%u Read reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
927                (int)rctx.jcr->JobId,
928                dcr->dev->reserved_device,
929                dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
930       }
931    }
932    if (!ok) {
933       rctx.have_volume = false;
934       free_dcr(dcr);
935       Dmsg1(110, "JobId=%u Not OK.\n", (int)rctx.jcr->JobId);
936       return 0;
937    }
938    return 1;
939 }
940
941 /*
942  * We "reserve" the drive by setting the ST_READ bit. No one else
943  *  should touch the drive until that is cleared.
944  *  This allows the DIR to "reserve" the device before actually
945  *  starting the job. 
946  */
947 static bool reserve_device_for_read(DCR *dcr)
948 {
949    DEVICE *dev = dcr->dev;
950    JCR *jcr = dcr->jcr;
951    bool ok = false;
952
953    ASSERT(dcr);
954
955    dev->dlock();  
956
957    if (is_device_unmounted(dev)) {             
958       Dmsg2(200, "JobId=%u Device %s is BLOCKED due to user unmount.\n", 
959          (int)jcr->JobId, dev->print_name());
960       Mmsg(jcr->errmsg, _("3601 JobId=%u device %s is BLOCKED due to user unmount.\n"),
961            jcr->JobId, dev->print_name());
962       queue_reserve_message(jcr);
963       goto bail_out;
964    }
965
966    if (dev->is_busy()) {
967       Dmsg5(200, "JobId=%u Device %s is busy ST_READ=%d num_writers=%d reserved=%d.\n", 
968          (int)jcr->JobId, dev->print_name(),
969          dev->state & ST_READ?1:0, dev->num_writers, dev->reserved_device);
970       Mmsg(jcr->errmsg, _("3602 JobId=%u device %s is busy (already reading/writing).\n"),
971             jcr->JobId, dev->print_name());
972       queue_reserve_message(jcr);
973       goto bail_out;
974    }
975
976    dev->clear_append();
977    dev->set_read();
978    ok = true;
979    dev->reserved_device++;
980    Dmsg4(100, "JobId=%u Inc reserve=%d dev=%s %p\n", (int)jcr->JobId,
981       dev->reserved_device, dev->print_name(), dev);
982    dcr->reserved_device = true;
983
984 bail_out:
985    dev->dunlock();
986    return ok;
987 }
988
989
990 /*
991  * We reserve the device for appending by incrementing the 
992  *  reserved_device. We do virtually all the same work that
993  *  is done in acquire_device_for_append(), but we do
994  *  not attempt to mount the device. This routine allows
995  *  the DIR to reserve multiple devices before *really* 
996  *  starting the job. It also permits the SD to refuse 
997  *  certain devices (not up, ...).
998  *
999  * Note, in reserving a device, if the device is for the
1000  *  same pool and the same pool type, then it is acceptable.
1001  *  The Media Type has already been checked. If we are
1002  *  the first tor reserve the device, we put the pool
1003  *  name and pool type in the device record.
1004  */
1005 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx)
1006 {
1007    JCR *jcr = dcr->jcr;
1008    DEVICE *dev = dcr->dev;
1009    bool ok = false;
1010
1011    ASSERT(dcr);
1012
1013    dev->dlock();
1014
1015    /* If device is being read, we cannot write it */
1016    if (dev->can_read()) {
1017       Mmsg(jcr->errmsg, _("3603 JobId=%u device %s is busy reading.\n"), 
1018          jcr->JobId, dev->print_name());
1019       Dmsg1(110, "%s", jcr->errmsg);
1020       queue_reserve_message(jcr);
1021       goto bail_out;
1022    }
1023
1024    /* If device is unmounted, we are out of luck */
1025    if (is_device_unmounted(dev)) {
1026       Mmsg(jcr->errmsg, _("3604 JobId=%u device %s is BLOCKED due to user unmount.\n"), 
1027          jcr->JobId, dev->print_name());
1028       Dmsg1(110, "%s", jcr->errmsg);
1029       queue_reserve_message(jcr);
1030       goto bail_out;
1031    }
1032
1033    Dmsg2(110, "JobId=%u reserve_append device is %s\n", 
1034        (int)jcr->JobId, dev->is_tape()?"tape":"disk");
1035
1036    /* Now do detailed tests ... */
1037    if (can_reserve_drive(dcr, rctx) != 1) {
1038       Dmsg1(110, "JobId=%u can_reserve_drive!=1\n", (int)jcr->JobId);
1039       goto bail_out;
1040    }
1041
1042    dev->reserved_device++;
1043    Dmsg4(100, "JobId=%u Inc reserve=%d dev=%s %p\n", (int)jcr->JobId, dev->reserved_device, 
1044       dev->print_name(), dev);
1045    dcr->reserved_device = true;
1046    ok = true;
1047
1048 bail_out:
1049    dev->dunlock();
1050    return ok;
1051 }
1052
1053 /*
1054  * Returns: 1 if drive can be reserved
1055  *          0 if we should wait
1056  *         -1 on error or impossibility
1057  */
1058 static int can_reserve_drive(DCR *dcr, RCTX &rctx) 
1059 {
1060    DEVICE *dev = dcr->dev;
1061    JCR *jcr = dcr->jcr;
1062
1063    Dmsg6(110, "JobId=%u PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
1064          (int)jcr->JobId,
1065          rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
1066          rctx.autochanger_only, rctx.any_drive);
1067
1068    /* setting any_drive overrides PreferMountedVols flag */
1069    if (!rctx.any_drive) {
1070       /*
1071        * When PreferMountedVols is set, we keep track of the 
1072        *  drive in use that has the least number of writers, then if
1073        *  no unmounted drive is found, we try that drive. This   
1074        *  helps spread the load to the least used drives.  
1075        */
1076       if (rctx.try_low_use_drive && dev == rctx.low_use_drive) {
1077          Dmsg3(110, "OK dev=%s == low_drive=%s. JobId=%u\n",
1078             dev->print_name(), rctx.low_use_drive->print_name(), jcr->JobId);
1079          return 1;
1080       }
1081       /* If he wants a free drive, but this one is busy, no go */
1082       if (!rctx.PreferMountedVols && dev->is_busy()) {
1083          /* Save least used drive */
1084          if ((dev->num_writers + dev->reserved_device) < rctx.num_writers) {
1085             rctx.num_writers = dev->num_writers + dev->reserved_device;
1086             rctx.low_use_drive = dev;
1087             Dmsg3(110, "JobId=%u set low use drive=%s num_writers=%d\n", 
1088                (int)jcr->JobId, dev->print_name(), rctx.num_writers);
1089          } else {
1090             Dmsg2(110, "JobId=%u not low use num_writers=%d\n", 
1091                (int)jcr->JobId, dev->num_writers+dev->reserved_device);
1092          }
1093          Dmsg1(110, "failed: !prefMnt && busy. JobId=%u\n", jcr->JobId);
1094          Mmsg(jcr->errmsg, _("3605 JobId=%u wants free drive but device %s is busy.\n"), 
1095             jcr->JobId, dev->print_name());
1096          queue_reserve_message(jcr);
1097          return 0;
1098       }
1099
1100       /* Check for prefer mounted volumes */
1101 //    if (rctx.PreferMountedVols && !dev->VolHdr.VolumeName[0] && dev->is_tape()) {
1102       if (rctx.PreferMountedVols && !dev->vol && dev->is_tape()) {
1103          Mmsg(jcr->errmsg, _("3606 JobId=%u prefers mounted drives, but drive %s has no Volume.\n"), 
1104             jcr->JobId, dev->print_name());
1105          queue_reserve_message(jcr);
1106          Dmsg1(110, "failed: want mounted -- no vol JobId=%u\n", (uint32_t)jcr->JobId);
1107          return 0;                 /* No volume mounted */
1108       }
1109
1110       /* Check for exact Volume name match */
1111       /*  ***FIXME***  use dev->vol.VolumeName */
1112       if (rctx.exact_match && rctx.have_volume &&
1113           strcmp(dev->VolHdr.VolumeName, rctx.VolumeName) != 0) {
1114          Mmsg(jcr->errmsg, _("3607 JobId=%u wants Vol=\"%s\" drive has Vol=\"%s\" on drive %s.\n"), 
1115             jcr->JobId, rctx.VolumeName, dev->VolHdr.VolumeName, 
1116             dev->print_name());
1117          queue_reserve_message(jcr);
1118          Dmsg3(110, "JobId=%u failed: Not exact match have=%s want=%s\n",
1119                (int)jcr->JobId, dev->VolHdr.VolumeName, rctx.VolumeName);
1120          return 0;
1121       }
1122    }
1123
1124    /* Check for unused autochanger drive */
1125    /* ***FIXME*** use !dev->is_busy() */
1126    if (rctx.autochanger_only && dev->num_writers == 0 &&
1127        dev->VolHdr.VolumeName[0] == 0) {
1128       /* Device is available but not yet reserved, reserve it for us */
1129       Dmsg2(100, "OK Res Unused autochanger %s JobId=%u.\n",
1130          dev->print_name(), jcr->JobId);
1131       bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
1132       bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
1133       return 1;                       /* reserve drive */
1134    }
1135
1136    /*
1137     * Handle the case that there are no writers
1138     */
1139    if (dev->num_writers == 0) {
1140       /* Now check if there are any reservations on the drive */
1141       if (dev->reserved_device) {           
1142          /* Now check if we want the same Pool and pool type */
1143          if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
1144              strcmp(dev->pool_type, dcr->pool_type) == 0) {
1145             /* OK, compatible device */
1146             Dmsg2(100, "OK dev: %s num_writers=0, reserved, pool matches JobId=%u\n",
1147                dev->print_name(), jcr->JobId);
1148             return 1;
1149          } else {
1150             /* Drive Pool not suitable for us */
1151             Mmsg(jcr->errmsg, _(
1152 "3608 JobId=%u wants Pool=\"%s\" but have Pool=\"%s\" nreserve=%d on drive %s.\n"), 
1153                   jcr->JobId, dcr->pool_name, dev->pool_name,
1154                   dev->reserved_device, dev->print_name());
1155             queue_reserve_message(jcr);
1156             Dmsg3(110, "JobId=%u failed: busy num_writers=0, reserved, pool=%s wanted=%s\n",
1157                (int)jcr->JobId, dev->pool_name, dcr->pool_name);
1158             return 0;                 /* wait */
1159          }
1160       } else if (dev->can_append()) {
1161          /* Device in append mode, check if changing pool */
1162          if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
1163              strcmp(dev->pool_type, dcr->pool_type) == 0) {
1164             Dmsg2(100, "OK dev: %s num_writers=0, can_append, pool matches. JobId=%u\n",
1165                dev->print_name(), jcr->JobId);
1166             /* OK, compatible device */
1167             return 1;
1168          } else {
1169             /* Changing pool, unload old tape if any in drive */
1170             Dmsg1(100, "JobId=%u OK dev: num_writers=0, not reserved, pool change, unload changer\n",
1171                 (int)jcr->JobId);
1172             unload_autochanger(dcr, 0);
1173          }
1174       }
1175       /* Device is available but not yet reserved, reserve it for us */
1176       Dmsg2(100, "OK Dev avail reserved %s JobId=%u\n", dev->print_name(),
1177          jcr->JobId);
1178       bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
1179       bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
1180       return 1;                       /* reserve drive */
1181    }
1182
1183    /*
1184     * Check if the device is in append mode with writers (i.e.
1185     *  available if pool is the same).
1186     */
1187    if (dev->can_append() || dev->num_writers > 0) {
1188       /* Yes, now check if we want the same Pool and pool type */
1189       if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
1190           strcmp(dev->pool_type, dcr->pool_type) == 0) {
1191          Dmsg2(100, "OK dev: %s num_writers>=0, can_append, pool matches. JobId=%u\n",
1192             dev->print_name(), jcr->JobId);
1193          /* OK, compatible device */
1194          return 1;
1195       } else {
1196          /* Drive Pool not suitable for us */
1197          Mmsg(jcr->errmsg, _("3609 JobId=%u wants Pool=\"%s\" but has Pool=\"%s\" on drive %s.\n"), 
1198                jcr->JobId, dcr->pool_name, dev->pool_name, dev->print_name());
1199          queue_reserve_message(jcr);
1200          Dmsg3(110, "JobId=%u failed: busy num_writers>0, can_append, pool=%s wanted=%s\n",
1201             (int)jcr->JobId, dev->pool_name, dcr->pool_name);
1202          return 0;                    /* wait */
1203       }
1204    } else {
1205       Pmsg1(000, _("Logic error!!!! JobId=%u Should not get here.\n"), (int)jcr->JobId);
1206       Mmsg(jcr->errmsg, _("3910 JobId=%u Logic error!!!! drive %s Should not get here.\n"),
1207             jcr->JobId, dev->print_name());
1208       queue_reserve_message(jcr);
1209       Jmsg0(jcr, M_FATAL, 0, _("Logic error!!!! Should not get here.\n"));
1210       return -1;                      /* error, should not get here */
1211    }
1212    Mmsg(jcr->errmsg, _("3911 JobId=%u failed reserve drive %s.\n"), 
1213          jcr->JobId, dev->print_name());
1214    queue_reserve_message(jcr);
1215    Dmsg2(110, "failed: No reserve %s JobId=%u\n", dev->print_name(), jcr->JobId);
1216    return 0;
1217 }
1218
1219 /*
1220  * search_lock is already set on entering this routine 
1221  */
1222 static void queue_reserve_message(JCR *jcr)
1223 {
1224    int i;   
1225    alist *msgs = jcr->reserve_msgs;
1226    char *msg;
1227
1228    if (!msgs) {
1229       return;
1230    }
1231    /*
1232     * Look for duplicate message.  If found, do
1233     * not insert
1234     */
1235    for (i=msgs->size()-1; i >= 0; i--) {
1236       msg = (char *)msgs->get(i);
1237       if (!msg) {
1238          return;
1239       }
1240       /* Comparison based on 4 digit message number */
1241       if (strncmp(msg, jcr->errmsg, 4) == 0) {
1242          return;
1243       }
1244    }      
1245    /* Message unique, so insert it */
1246    jcr->reserve_msgs->push(bstrdup(jcr->errmsg));
1247 }
1248
1249 /*
1250  * Send any reservation messages queued for this jcr
1251  */
1252 void send_drive_reserve_messages(JCR *jcr, void sendit(const char *msg, int len, void *sarg), void *arg)
1253 {
1254    int i;
1255    alist *msgs;
1256    char *msg;
1257
1258    lock_reservations();
1259    msgs = jcr->reserve_msgs;
1260    if (!msgs || msgs->size() == 0) {
1261       unlock_reservations();
1262       return;
1263    }
1264    for (i=msgs->size()-1; i >= 0; i--) {
1265       msg = (char *)msgs->get(i);
1266       if (msg) {
1267          sendit("   ", 3, arg);
1268          sendit(msg, strlen(msg), arg);
1269       } else {
1270          break;
1271       }
1272    }
1273    unlock_reservations();
1274 }