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