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