]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/reserve.c
- Add more jcr methods and make mutex and use_count private.
[bacula/bacula] / bacula / src / stored / reserve.c
1 /*
2  *   Drive reservation functions for Storage Daemon
3  *
4  *   Kern Sibbald, MM
5  *
6  *   Split from job.c and acquire.c June 2005
7  *
8  *   Version $Id$
9  *
10  */
11 /*
12    Copyright (C) 2000-2006 Kern Sibbald
13
14    This program is free software; you can redistribute it and/or
15    modify it under the terms of the GNU General Public License
16    version 2 as amended with additional clauses defined in the
17    file LICENSE in the main source directory.
18
19    This program is distributed in the hope that it will be useful,
20    but WITHOUT ANY WARRANTY; without even the implied warranty of
21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
22    the file LICENSE for additional details.
23
24  */
25
26 #include "bacula.h"
27 #include "stored.h"
28
29 static dlist *vol_list = NULL;
30 static pthread_mutex_t vol_list_lock = PTHREAD_MUTEX_INITIALIZER;
31
32 /* Forward referenced functions */
33 static int can_reserve_drive(DCR *dcr, RCTX &rctx);
34 static int reserve_device(RCTX &rctx);
35 static bool reserve_device_for_read(DCR *dcr);
36 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx);
37 static bool use_storage_cmd(JCR *jcr);
38 static void queue_reserve_message(JCR *jcr);
39
40 /* Requests from the Director daemon */
41 static char use_storage[]  = "use storage=%127s media_type=%127s "
42    "pool_name=%127s pool_type=%127s append=%d copy=%d stripe=%d\n";
43 static char use_device[]  = "use device=%127s\n";
44
45 /* Responses sent to Director daemon */
46 static char OK_device[] = "3000 OK use device device=%s\n";
47 static char NO_device[] = "3924 Device \"%s\" not in SD Device resources.\n";
48 static char BAD_use[]   = "3913 Bad use command: %s\n";
49
50 bool use_cmd(JCR *jcr) 
51 {
52    /*
53     * Get the device, media, and pool information
54     */
55    if (!use_storage_cmd(jcr)) {
56       set_jcr_job_status(jcr, JS_ErrorTerminated);
57       memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
58       return false;
59    }
60    return true;
61 }
62
63 static int my_compare(void *item1, void *item2)
64 {
65    return strcmp(((VOLRES *)item1)->vol_name, ((VOLRES *)item2)->vol_name);
66 }
67
68 static brwlock_t reservation_lock;
69
70 void init_reservations_lock()
71 {
72    int errstat;
73    if ((errstat=rwl_init(&reservation_lock)) != 0) {
74       berrno be;
75       Emsg1(M_ABORT, 0, _("Unable to initialize reservation lock. ERR=%s\n"),
76             be.strerror(errstat));
77    }
78
79 }
80
81 void term_reservations_lock()
82 {
83    rwl_destroy(&reservation_lock);
84 }
85
86 /* This applies to a drive and to Volumes */
87 void lock_reservations()
88 {
89    int errstat;
90    if ((errstat=rwl_writelock(&reservation_lock)) != 0) {
91       berrno be;
92       Emsg2(M_ABORT, 0, "rwl_writelock failure. stat=%d: ERR=%s\n",
93            errstat, be.strerror(errstat));
94    }
95 }
96
97 void unlock_reservations()
98 {
99    int errstat;
100    if ((errstat=rwl_writeunlock(&reservation_lock)) != 0) {
101       berrno be;
102       Emsg2(M_ABORT, 0, "rwl_writeunlock failure. stat=%d: ERR=%s\n",
103            errstat, be.strerror(errstat));
104    }
105 }
106
107
108 /*
109  * Put a new Volume entry in the Volume list. This
110  *  effectively reserves the volume so that it will
111  *  not be mounted again.
112  *
113  *  Return: VOLRES entry on success
114  *          NULL if the Volume is already in the list
115  */
116 VOLRES *new_volume(DCR *dcr, const char *VolumeName)
117 {
118    VOLRES *vol, *nvol;
119
120    Dmsg1(400, "new_volume %s\n", VolumeName);
121    /* 
122     * We lock the reservations system here to ensure
123     *  when adding a new volume that no newly scheduled
124     *  job can reserve it.
125     */
126    lock_reservations();
127    P(vol_list_lock);
128    if (dcr->dev) {
129 again:
130       foreach_dlist(vol, vol_list) {
131          if (vol && vol->dev == dcr->dev) {
132             vol_list->remove(vol);
133             if (vol->vol_name) {
134                free(vol->vol_name);
135             }
136             free(vol);
137             goto again;
138          }
139       }
140    }
141    vol = (VOLRES *)malloc(sizeof(VOLRES));
142    memset(vol, 0, sizeof(VOLRES));
143    vol->vol_name = bstrdup(VolumeName);
144    vol->dev = dcr->dev;
145    vol->dcr = dcr;
146    Dmsg2(100, "New Vol=%s dev=%s\n", VolumeName, dcr->dev->print_name());
147    nvol = (VOLRES *)vol_list->binary_insert(vol, my_compare);
148    if (nvol != vol) {
149       free(vol->vol_name);
150       free(vol);
151       vol = NULL;
152       if (dcr->dev) {
153          DEVICE *dev = nvol->dev;
154          if (!dev->is_busy()) {
155             Dmsg3(100, "Swap vol=%s from dev=%s to %s\n", VolumeName,
156                dev->print_name(), dcr->dev->print_name());
157             nvol->dev = dcr->dev;
158             dev->VolHdr.VolumeName[0] = 0;
159          } else {
160             Dmsg3(100, "!!!! could not swap vol=%s from dev=%s to %s\n", VolumeName,
161                dev->print_name(), dcr->dev->print_name());
162          }
163       }
164    }
165    V(vol_list_lock);
166    unlock_reservations();
167    return vol;
168 }
169
170 /*
171  * Search for a Volume name in the Volume list.
172  *
173  *  Returns: VOLRES entry on success
174  *           NULL if the Volume is not in the list
175  */
176 VOLRES *find_volume(const char *VolumeName)
177 {
178    VOLRES vol, *fvol;
179    /* Do not lock reservations here */
180    P(vol_list_lock);
181    vol.vol_name = bstrdup(VolumeName);
182    fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
183    free(vol.vol_name);
184    V(vol_list_lock);
185    return fvol;
186 }
187
188 /*  
189  * Free a Volume from the Volume list
190  *
191  *  Returns: true if the Volume found and removed from the list
192  *           false if the Volume is not in the list
193  */
194 bool free_volume(DEVICE *dev)
195 {
196    VOLRES vol, *fvol;
197
198    P(vol_list_lock);
199    if (dev->VolHdr.VolumeName[0] == 0) {
200       Dmsg1(100, "free_volume: no vol on dev %s\n", dev->print_name());
201       /*
202        * Our device has no VolumeName listed, but
203        *  search the list for any Volume attached to
204        *  this device and remove it.
205        */
206       foreach_dlist(fvol, vol_list) {
207          if (fvol && fvol->dev == dev) {
208             vol_list->remove(fvol);
209             if (fvol->vol_name) {
210                Dmsg2(100, "free_volume %s dev=%s\n", fvol->vol_name, dev->print_name());
211                free(fvol->vol_name);
212             }
213             free(fvol);
214             break;
215          }
216       }
217       goto bail_out;
218    }
219    Dmsg1(400, "free_volume %s\n", dev->VolHdr.VolumeName);
220    vol.vol_name = bstrdup(dev->VolHdr.VolumeName);
221    fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
222    if (fvol) {
223       vol_list->remove(fvol);
224       Dmsg2(100, "free_volume %s dev=%s\n", fvol->vol_name, dev->print_name());
225       free(fvol->vol_name);
226       free(fvol);
227    }
228    free(vol.vol_name);
229    dev->VolHdr.VolumeName[0] = 0;
230 bail_out:
231    V(vol_list_lock);
232    return fvol != NULL;
233 }
234
235 /* Free volume reserved by this dcr but not attached to a dev */
236 void free_unused_volume(DCR *dcr)
237 {
238    VOLRES *vol;
239
240    P(vol_list_lock);
241    for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
242       if (vol->dcr == dcr && (vol->dev == NULL || 
243           strcmp(vol->vol_name, vol->dev->VolHdr.VolumeName) != 0)) {
244          vol_list->remove(vol);
245          Dmsg1(100, "free_unused_olume %s\n", vol->vol_name);
246          free(vol->vol_name);
247          free(vol);
248          break;
249       }
250    }
251    V(vol_list_lock);
252 }
253
254 /*
255  * List Volumes -- this should be moved to status.c
256  */
257 void list_volumes(BSOCK *user)  
258 {
259    VOLRES *vol;
260    P(vol_list_lock);
261    for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
262       if (vol->dev) {
263          bnet_fsend(user, "%s on device %s\n", vol->vol_name, vol->dev->print_name());
264       } else {
265          bnet_fsend(user, "%s\n", vol->vol_name);
266       }
267    }
268    V(vol_list_lock);
269 }
270       
271 /* Create the Volume list */
272 void create_volume_list()
273 {
274    VOLRES *dummy = NULL;
275    if (vol_list == NULL) {
276       vol_list = New(dlist(dummy, &dummy->link));
277    }
278 }
279
280 /* Release all Volumes from the list */
281 void free_volume_list()
282 {
283    VOLRES *vol;
284    if (!vol_list) {
285       return;
286    }
287    P(vol_list_lock);
288    for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
289       Dmsg3(000, "Unreleased Volume=%s dcr=0x%x dev=0x%x\n", vol->vol_name,
290          vol->dcr, vol->dev);
291    }
292    delete vol_list;
293    vol_list = NULL;
294    V(vol_list_lock);
295 }
296
297 bool is_volume_in_use(DCR *dcr)
298 {
299    VOLRES *vol = find_volume(dcr->VolumeName);
300    if (!vol) {
301       Dmsg1(100, "Vol=%s not in use.\n", dcr->VolumeName);
302       return false;                   /* vol not in list */
303    }
304    if (!vol->dev) {                   /* vol not attached to device */
305       Dmsg1(100, "Vol=%s has no dev.\n", dcr->VolumeName);
306       return false;
307    }
308    if (dcr->dev == vol->dev) {        /* same device OK */
309       Dmsg1(100, "Vol=%s on same dev.\n", dcr->VolumeName);
310       return false;
311    }
312    if (!vol->dev->is_busy()) {
313       Dmsg2(100, "Vol=%s dev=%s not busy.\n", dcr->VolumeName, vol->dev->print_name());
314       return false;
315    }
316    Dmsg2(100, "Vol=%s used by %s.\n", dcr->VolumeName, vol->dev->print_name());
317    return true;
318 }
319
320
321 /*
322  * We get the following type of information:
323  *
324  * use storage=xxx media_type=yyy pool_name=xxx pool_type=yyy append=1 copy=0 strip=0
325  *  use device=zzz
326  *  use device=aaa
327  *  use device=bbb
328  * use storage=xxx media_type=yyy pool_name=xxx pool_type=yyy append=0 copy=0 strip=0
329  *  use device=bbb
330  *
331  */
332 static bool use_storage_cmd(JCR *jcr)
333 {
334    POOL_MEM store_name, dev_name, media_type, pool_name, pool_type;
335    BSOCK *dir = jcr->dir_bsock;
336    int append;
337    bool ok;       
338    int Copy, Stripe;
339    DIRSTORE *store;
340    RCTX rctx;
341    char *msg;
342    alist *msgs;
343
344    memset(&rctx, 0, sizeof(RCTX));
345    rctx.jcr = jcr;
346    /*
347     * If there are multiple devices, the director sends us
348     *   use_device for each device that it wants to use.
349     */
350    jcr->dirstore = New(alist(10, not_owned_by_alist));
351    msgs = jcr->reserve_msgs = New(alist(10, not_owned_by_alist));  
352    do {
353       Dmsg1(100, "<dird: %s", dir->msg);
354       ok = sscanf(dir->msg, use_storage, store_name.c_str(), 
355                   media_type.c_str(), pool_name.c_str(), 
356                   pool_type.c_str(), &append, &Copy, &Stripe) == 7;
357       if (!ok) {
358          break;
359       }
360       unbash_spaces(store_name);
361       unbash_spaces(media_type);
362       unbash_spaces(pool_name);
363       unbash_spaces(pool_type);
364       store = new DIRSTORE;
365       jcr->dirstore->append(store);
366       memset(store, 0, sizeof(DIRSTORE));
367       store->device = New(alist(10));
368       bstrncpy(store->name, store_name, sizeof(store->name));
369       bstrncpy(store->media_type, media_type, sizeof(store->media_type));
370       bstrncpy(store->pool_name, pool_name, sizeof(store->pool_name));
371       bstrncpy(store->pool_type, pool_type, sizeof(store->pool_type));
372       store->append = append;
373
374       /* Now get all devices */
375       while (bnet_recv(dir) >= 0) {
376          Dmsg1(100, "<dird device: %s", dir->msg);
377          ok = sscanf(dir->msg, use_device, dev_name.c_str()) == 1;
378          if (!ok) {
379             break;
380          }
381          unbash_spaces(dev_name);
382          store->device->append(bstrdup(dev_name.c_str()));
383       }
384    }  while (ok && bnet_recv(dir) >= 0);
385
386 #ifdef DEVELOPER
387    /* This loop is debug code and can be removed */
388    /* ***FIXME**** remove after 1.38 release */
389    char *device_name;
390    foreach_alist(store, jcr->dirstore) {
391       Dmsg5(110, "Storage=%s media_type=%s pool=%s pool_type=%s append=%d\n", 
392          store->name, store->media_type, store->pool_name, 
393          store->pool_type, store->append);
394       foreach_alist(device_name, store->device) {
395          Dmsg1(110, "   Device=%s\n", device_name);
396       }
397    }
398 #endif
399
400    init_jcr_device_wait_timers(jcr);
401    /*                    
402     * At this point, we have a list of all the Director's Storage
403     *  resources indicated for this Job, which include Pool, PoolType,
404     *  storage name, and Media type.     
405     * Then for each of the Storage resources, we have a list of
406     *  device names that were given.
407     *
408     * Wiffle through them and find one that can do the backup.
409     */
410    if (ok) {
411       bool first = true;           /* print wait message once */
412       rctx.notify_dir = true;
413       for ( ; !job_canceled(jcr); ) {
414          lock_reservations();           /* only one thread at a time */
415          while ((msg = (char *)msgs->pop())) {
416             free(msg);
417          }
418          rctx.suitable_device = false;
419          rctx.have_volume = false;
420          rctx.any_drive = false;
421          if (!jcr->PreferMountedVols) {
422             /* Look for unused drives in autochangers */
423             rctx.num_writers = 20000000;   /* start with impossible number */
424             rctx.low_use_drive = NULL;
425             rctx.PreferMountedVols = false;                
426             rctx.exact_match = false;
427             rctx.autochanger_only = true;
428             Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
429                rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
430                rctx.autochanger_only, rctx.any_drive);
431             if ((ok = find_suitable_device_for_job(jcr, rctx))) {
432                break;
433             }
434             /* Look through all drives possibly for low_use drive */
435             if (rctx.low_use_drive) {
436                rctx.try_low_use_drive = true;
437                if ((ok = find_suitable_device_for_job(jcr, rctx))) {
438                   break;
439                }
440                rctx.try_low_use_drive = false;
441             }
442             rctx.autochanger_only = false;
443             Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
444                rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
445                rctx.autochanger_only, rctx.any_drive);
446             if ((ok = find_suitable_device_for_job(jcr, rctx))) {
447                break;
448             }
449          }
450          /* Look for an exact match all drives */
451          rctx.PreferMountedVols = true;
452          rctx.exact_match = true;
453          rctx.autochanger_only = false;
454          Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
455             rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
456             rctx.autochanger_only, rctx.any_drive);
457          if ((ok = find_suitable_device_for_job(jcr, rctx))) {
458             break;
459          }
460          /* Look for any mounted drive */
461          rctx.exact_match = false;
462          Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
463             rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
464             rctx.autochanger_only, rctx.any_drive);
465          if ((ok = find_suitable_device_for_job(jcr, rctx))) {
466             break;
467          }
468          /* Try any drive */
469          rctx.any_drive = true;
470          Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
471             rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
472             rctx.autochanger_only, rctx.any_drive);
473          if ((ok = find_suitable_device_for_job(jcr, rctx))) {
474             break;
475          }
476          /* Unlock before possible wait */
477          unlock_reservations();
478          if (!rctx.suitable_device || !wait_for_device(jcr, first)) {
479             Dmsg0(100, "Fail. !suitable_device || !wait_for_device\n");
480             break;       /* Get out, failure ... */
481          }   
482          first = false;
483          bnet_sig(dir, BNET_HEARTBEAT);  /* Inform Dir that we are alive */
484       }
485       /* Note if !ok then search_lock is already cleared */
486       if (ok) {
487          unlock_reservations();
488          goto all_done;
489       } 
490
491       /*
492        * If we get here, there are no suitable devices available, which
493        *  means nothing configured.  If a device is suitable but busy
494        *  with another Volume, we will not come here.
495        */
496       if (verbose) {
497          unbash_spaces(dir->msg);
498          pm_strcpy(jcr->errmsg, dir->msg);
499          Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
500       }
501       Jmsg(jcr, M_FATAL, 0, _("\n"
502          "     Device \"%s\" with MediaType \"%s\" requested by DIR not found in SD Device resources.\n"),
503            dev_name.c_str(), media_type.c_str());
504       bnet_fsend(dir, NO_device, dev_name.c_str());
505
506       Dmsg1(100, ">dird: %s", dir->msg);
507    } else {
508       unbash_spaces(dir->msg);
509       pm_strcpy(jcr->errmsg, dir->msg);
510       if (verbose) {
511          Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
512       }
513       bnet_fsend(dir, BAD_use, jcr->errmsg);
514       Dmsg1(100, ">dird: %s", dir->msg);
515    }
516
517 all_done:
518    release_msgs(jcr);
519    return ok;
520 }
521
522 void release_msgs(JCR *jcr)
523 {
524    alist *msgs = jcr->reserve_msgs;
525    char *msg;
526
527    if (!msgs) {
528       return;
529    }
530    lock_reservations();
531    while ((msg = (char *)msgs->pop())) {
532       free(msg);
533    }
534    delete msgs;
535    jcr->reserve_msgs = NULL;
536    unlock_reservations();
537 }
538
539 /*
540  * Search for a device suitable for this job.
541  */
542 bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx)
543 {
544    bool ok;
545    DIRSTORE *store;
546    char *device_name;
547
548    /* 
549     * For each storage device that the user specified, we
550     *  search and see if there is a resource for that device.
551     */
552    Dmsg4(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d\n",
553       rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
554       rctx.autochanger_only);
555    ok = false;
556    foreach_alist(store, jcr->dirstore) {
557       rctx.store = store;
558       foreach_alist(device_name, store->device) {
559          int stat;
560          rctx.device_name = device_name;
561          stat = search_res_for_device(rctx); 
562          if (stat == 1) {             /* found available device */
563             Dmsg1(100, "Suitable device found=%s\n", device_name);
564             ok = true;
565             break;
566          } else if (stat == 0) {      /* device busy */
567             Dmsg1(110, "Suitable device found=%s, not used: busy\n", device_name);
568          } else {
569             /* otherwise error */
570             Dmsg0(110, "No suitable device found.\n");
571          }
572       }
573       if (ok) {
574          break;
575       }
576    }
577
578    return ok;
579 }
580
581 /*
582  * Search for a particular storage device with particular storage
583  *  characteristics (MediaType).
584  */
585 int search_res_for_device(RCTX &rctx) 
586 {
587    AUTOCHANGER *changer;
588    BSOCK *dir = rctx.jcr->dir_bsock;
589    bool ok;
590    int stat;
591
592    Dmsg1(110, "Search res for %s\n", rctx.device_name);
593    /* Look through Autochangers first */
594    foreach_res(changer, R_AUTOCHANGER) {
595       Dmsg1(150, "Try match changer res=%s\n", changer->hdr.name);
596       /* Find resource, and make sure we were able to open it */
597       if (fnmatch(rctx.device_name, changer->hdr.name, 0) == 0) {
598          /* Try each device in this AutoChanger */
599          foreach_alist(rctx.device, changer->device) {
600             Dmsg1(110, "Try changer device %s\n", rctx.device->hdr.name);
601             stat = reserve_device(rctx);
602             if (stat != 1) {             /* try another device */
603                continue;
604             }
605             POOL_MEM dev_name;
606             if (rctx.store->append == SD_APPEND) {
607                Dmsg2(100, "Device %s reserved=%d for append.\n", rctx.device->hdr.name,
608                   rctx.jcr->dcr->dev->reserved_device);
609             } else {
610                Dmsg2(100, "Device %s reserved=%d for read.\n", rctx.device->hdr.name,
611                   rctx.jcr->read_dcr->dev->reserved_device);
612             }
613             if (rctx.notify_dir) {
614                pm_strcpy(dev_name, rctx.device->hdr.name);
615                bash_spaces(dev_name);
616                ok = bnet_fsend(dir, OK_device, dev_name.c_str());  /* Return real device name */
617                Dmsg1(100, ">dird changer: %s", dir->msg);
618             } else {
619                ok = true;
620             }
621             return ok ? 1 : -1;
622          }
623       }
624    }
625
626    /* Now if requested look through regular devices */
627    if (!rctx.autochanger_only) {
628       foreach_res(rctx.device, R_DEVICE) {
629          Dmsg1(150, "Try match res=%s\n", rctx.device->hdr.name);
630          /* Find resource, and make sure we were able to open it */
631          if (fnmatch(rctx.device_name, rctx.device->hdr.name, 0) == 0) {
632             stat = reserve_device(rctx);
633             if (stat != 1) {
634                return stat;
635             }
636             if (rctx.notify_dir) {
637                bash_spaces(rctx.device_name);
638                ok = bnet_fsend(dir, OK_device, rctx.device_name);
639                Dmsg1(100, ">dird dev: %s", dir->msg);
640             } else {
641                ok = true;
642             }
643             return ok ? 1 : -1;
644          }
645       }
646    }
647    return -1;                    /* nothing found */
648 }
649
650 /*
651  *  Try to reserve a specific device.
652  *
653  *  Returns: 1 -- OK, have DCR
654  *           0 -- must wait
655  *          -1 -- fatal error
656  */
657 static int reserve_device(RCTX &rctx)
658 {
659    bool ok;
660    DCR *dcr;
661    const int name_len = MAX_NAME_LENGTH;
662
663    /* Make sure MediaType is OK */
664    Dmsg2(110, "MediaType device=%s request=%s\n",
665          rctx.device->media_type, rctx.store->media_type);
666    if (strcmp(rctx.device->media_type, rctx.store->media_type) != 0) {
667       return -1;
668    }
669
670    /* Make sure device exists -- i.e. we can stat() it */
671    if (!rctx.device->dev) {
672       rctx.device->dev = init_dev(rctx.jcr, rctx.device);
673    }
674    if (!rctx.device->dev) {
675       if (rctx.device->changer_res) {
676         Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
677            "     Device \"%s\" in changer \"%s\" requested by DIR could not be opened or does not exist.\n"),
678              rctx.device->hdr.name, rctx.device_name);
679       } else {
680          Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
681             "     Device \"%s\" requested by DIR could not be opened or does not exist.\n"),
682               rctx.device_name);
683       }
684       return -1;  /* no use waiting */
685    }  
686
687    rctx.suitable_device = true;
688    Dmsg2(110, "Try reserve %s JobId=%u\n", rctx.device->hdr.name,
689          rctx.jcr->JobId);
690    dcr = new_dcr(rctx.jcr, rctx.device->dev);
691    if (!dcr) {
692       BSOCK *dir = rctx.jcr->dir_bsock;
693       bnet_fsend(dir, _("3926 Could not get dcr for device: %s\n"), rctx.device_name);
694       Dmsg1(100, ">dird: %s", dir->msg);
695       return -1;
696    }
697    bstrncpy(dcr->pool_name, rctx.store->pool_name, name_len);
698    bstrncpy(dcr->pool_type, rctx.store->pool_type, name_len);
699    bstrncpy(dcr->media_type, rctx.store->media_type, name_len);
700    bstrncpy(dcr->dev_name, rctx.device_name, name_len);
701    if (rctx.store->append == SD_APPEND) {
702       if (rctx.exact_match && !rctx.have_volume) {
703          dcr->any_volume = true;
704          if (dir_find_next_appendable_volume(dcr)) {
705             bstrncpy(rctx.VolumeName, dcr->VolumeName, sizeof(rctx.VolumeName));
706             Dmsg2(100, "JobId=%u looking for Volume=%s\n", rctx.jcr->JobId, rctx.VolumeName);
707             rctx.have_volume = true;
708          } else {
709             Dmsg0(100, "No next volume found\n");
710             rctx.VolumeName[0] = 0;
711         }
712       }
713       ok = reserve_device_for_append(dcr, rctx);
714       if (ok) {
715          rctx.jcr->dcr = dcr;
716          Dmsg5(100, "Reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
717                dcr->dev->reserved_device,
718                dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
719       }
720    } else {
721       ok = reserve_device_for_read(dcr);
722       if (ok) {
723          rctx.jcr->read_dcr = dcr;
724          Dmsg5(100, "Read reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
725                dcr->dev->reserved_device,
726                dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
727       }
728    }
729    if (!ok) {
730       free_dcr(dcr);
731       Dmsg0(110, "Not OK.\n");
732       return 0;
733    }
734    return 1;
735 }
736
737 /*
738  * We "reserve" the drive by setting the ST_READ bit. No one else
739  *  should touch the drive until that is cleared.
740  *  This allows the DIR to "reserve" the device before actually
741  *  starting the job. 
742  */
743 static bool reserve_device_for_read(DCR *dcr)
744 {
745    DEVICE *dev = dcr->dev;
746    JCR *jcr = dcr->jcr;
747    bool ok = false;
748
749    ASSERT(dcr);
750
751    P(dev->mutex);
752
753    if (is_device_unmounted(dev)) {             
754       Dmsg1(200, "Device %s is BLOCKED due to user unmount.\n", dev->print_name());
755       Mmsg(jcr->errmsg, _("3601 JobId=%u device %s is BLOCKED due to user unmount.\n"),
756            jcr->JobId, dev->print_name());
757       queue_reserve_message(jcr);
758       goto bail_out;
759    }
760
761    if (dev->is_busy()) {
762       Dmsg4(200, "Device %s is busy ST_READ=%d num_writers=%d reserved=%d.\n", dev->print_name(),
763          dev->state & ST_READ?1:0, dev->num_writers, dev->reserved_device);
764       Mmsg(jcr->errmsg, _("3602 JobId=%u device %s is busy (already reading/writing).\n"),
765             jcr->JobId, dev->print_name());
766       queue_reserve_message(jcr);
767       goto bail_out;
768    }
769
770    dev->clear_append();
771    dev->set_read();
772    ok = true;
773    dev->reserved_device++;
774    Dmsg3(100, "Inc reserve=%d dev=%s %p\n", dev->reserved_device, 
775       dev->print_name(), dev);
776    dcr->reserved_device = true;
777
778 bail_out:
779    V(dev->mutex);
780    return ok;
781 }
782
783
784 /*
785  * We reserve the device for appending by incrementing the 
786  *  reserved_device. We do virtually all the same work that
787  *  is done in acquire_device_for_append(), but we do
788  *  not attempt to mount the device. This routine allows
789  *  the DIR to reserve multiple devices before *really* 
790  *  starting the job. It also permits the SD to refuse 
791  *  certain devices (not up, ...).
792  *
793  * Note, in reserving a device, if the device is for the
794  *  same pool and the same pool type, then it is acceptable.
795  *  The Media Type has already been checked. If we are
796  *  the first tor reserve the device, we put the pool
797  *  name and pool type in the device record.
798  */
799 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx)
800 {
801    JCR *jcr = dcr->jcr;
802    DEVICE *dev = dcr->dev;
803    bool ok = false;
804
805    ASSERT(dcr);
806
807    P(dev->mutex);
808
809    /* If device is being read, we cannot write it */
810    if (dev->can_read()) {
811       Mmsg(jcr->errmsg, _("3603 JobId=%u device %s is busy reading.\n"), 
812          jcr->JobId, dev->print_name());
813       Dmsg1(110, "%s", jcr->errmsg);
814       queue_reserve_message(jcr);
815       goto bail_out;
816    }
817
818    /* If device is unmounted, we are out of luck */
819    if (is_device_unmounted(dev)) {
820       Mmsg(jcr->errmsg, _("3604 JobId=%u device %s is BLOCKED due to user unmount.\n"), 
821          jcr->JobId, dev->print_name());
822       Dmsg1(110, "%s", jcr->errmsg);
823       queue_reserve_message(jcr);
824       goto bail_out;
825    }
826
827    Dmsg1(110, "reserve_append device is %s\n", dev->is_tape()?"tape":"disk");
828
829    /* Now do detailed tests ... */
830    if (can_reserve_drive(dcr, rctx) != 1) {
831       Dmsg0(110, "can_reserve_drive!=1\n");
832       goto bail_out;
833    }
834
835    dev->reserved_device++;
836    Dmsg3(100, "Inc reserve=%d dev=%s %p\n", dev->reserved_device, 
837       dev->print_name(), dev);
838    dcr->reserved_device = true;
839    ok = true;
840
841 bail_out:
842    V(dev->mutex);
843    return ok;
844 }
845
846 /*
847  * Returns: 1 if drive can be reserved
848  *          0 if we should wait
849  *         -1 on error or impossibility
850  */
851 static int can_reserve_drive(DCR *dcr, RCTX &rctx) 
852 {
853    DEVICE *dev = dcr->dev;
854    JCR *jcr = dcr->jcr;
855
856    Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
857          rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
858          rctx.autochanger_only, rctx.any_drive);
859
860    /* setting any_drive overrides PreferMountedVols flag */
861    if (!rctx.any_drive) {
862       /*
863        * When PreferMountedVols is set, we keep track of the 
864        *  drive in use that has the least number of writers, then if
865        *  no unmounted drive is found, we try that drive. This   
866        *  helps spread the load to the least used drives.  
867        */
868       if (rctx.try_low_use_drive && dev == rctx.low_use_drive) {
869          Dmsg3(110, "OK dev=%s == low_drive=%s. JobId=%u\n",
870             dev->print_name(), rctx.low_use_drive->print_name(), jcr->JobId);
871          return 1;
872       }
873       /* If he wants a free drive, but this one is busy, no go */
874       if (!rctx.PreferMountedVols && dev->is_busy()) {
875          /* Save least used drive */
876          if ((dev->num_writers + dev->reserved_device) < rctx.num_writers) {
877             rctx.num_writers = dev->num_writers + dev->reserved_device;
878             rctx.low_use_drive = dev;
879             Dmsg2(110, "set low use drive=%s num_writers=%d\n", dev->print_name(),
880                rctx.num_writers);
881          } else {
882             Dmsg1(110, "not low use num_writers=%d\n", dev->num_writers+ 
883                dev->reserved_device);
884          }
885          Dmsg1(110, "failed: !prefMnt && busy. JobId=%u\n", jcr->JobId);
886          Mmsg(jcr->errmsg, _("3605 JobId=%u wants free drive but device %s is busy.\n"), 
887             jcr->JobId, dev->print_name());
888          queue_reserve_message(jcr);
889          return 0;
890       }
891
892       /* Check for prefer mounted volumes */
893       if (rctx.PreferMountedVols && !dev->VolHdr.VolumeName[0] && dev->is_tape()) {
894          Mmsg(jcr->errmsg, _("3606 JobId=%u wants mounted, but drive %s has no Volume.\n"), 
895             jcr->JobId, dev->print_name());
896          queue_reserve_message(jcr);
897          Dmsg1(110, "failed: want mounted -- no vol JobId=%u\n", jcr->JobId);
898          return 0;                 /* No volume mounted */
899       }
900
901       /* Check for exact Volume name match */
902       if (rctx.exact_match && rctx.have_volume &&
903           strcmp(dev->VolHdr.VolumeName, rctx.VolumeName) != 0) {
904          Mmsg(jcr->errmsg, _("3607 JobId=%u wants Vol=\"%s\" drive has Vol=\"%s\" on drive %s.\n"), 
905             jcr->JobId, rctx.VolumeName, dev->VolHdr.VolumeName, 
906             dev->print_name());
907          queue_reserve_message(jcr);
908          Dmsg2(110, "failed: Not exact match have=%s want=%s\n",
909                dev->VolHdr.VolumeName, rctx.VolumeName);
910          return 0;
911       }
912    }
913
914    /* Check for unused autochanger drive */
915    if (rctx.autochanger_only && dev->num_writers == 0 &&
916        dev->VolHdr.VolumeName[0] == 0) {
917       /* Device is available but not yet reserved, reserve it for us */
918       Dmsg2(100, "OK Res Unused autochanger %s JobId=%u.\n",
919          dev->print_name(), jcr->JobId);
920       bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
921       bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
922       return 1;                       /* reserve drive */
923    }
924
925    /*
926     * Handle the case that there are no writers
927     */
928    if (dev->num_writers == 0) {
929       /* Now check if there are any reservations on the drive */
930       if (dev->reserved_device) {           
931          /* Now check if we want the same Pool and pool type */
932          if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
933              strcmp(dev->pool_type, dcr->pool_type) == 0) {
934             /* OK, compatible device */
935             Dmsg2(100, "OK dev: %s num_writers=0, reserved, pool matches JobId=%u\n",
936                dev->print_name(), jcr->JobId);
937             return 1;
938          } else {
939             /* Drive Pool not suitable for us */
940             Mmsg(jcr->errmsg, _("3608 JobId=%u wants Pool=\"%s\" but have Pool=\"%s\" on drive %s.\n"), 
941                   jcr->JobId, dcr->pool_name, dev->pool_name, dev->print_name());
942             queue_reserve_message(jcr);
943             Dmsg2(110, "failed: busy num_writers=0, reserved, pool=%s wanted=%s\n",
944                dev->pool_name, dcr->pool_name);
945             return 0;                 /* wait */
946          }
947       } else if (dev->can_append()) {
948          /* Device in append mode, check if changing pool */
949          if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
950              strcmp(dev->pool_type, dcr->pool_type) == 0) {
951             Dmsg2(100, "OK dev: %s num_writers=0, can_append, pool matches. JobId=%u\n",
952                dev->print_name(), jcr->JobId);
953             /* OK, compatible device */
954             return 1;
955          } else {
956             /* Changing pool, unload old tape if any in drive */
957             Dmsg0(100, "OK dev: num_writers=0, not reserved, pool change, unload changer\n");
958             unload_autochanger(dcr, 0);
959          }
960       }
961       /* Device is available but not yet reserved, reserve it for us */
962       Dmsg2(100, "OK Dev avail reserved %s JobId=%u\n", dev->print_name(),
963          jcr->JobId);
964       bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
965       bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
966       return 1;                       /* reserve drive */
967    }
968
969    /*
970     * Check if the device is in append mode with writers (i.e.
971     *  available if pool is the same).
972     */
973    if (dev->can_append() || dev->num_writers > 0) {
974       /* Yes, now check if we want the same Pool and pool type */
975       if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
976           strcmp(dev->pool_type, dcr->pool_type) == 0) {
977          Dmsg2(100, "OK dev: %s num_writers>=0, can_append, pool matches. JobId=%u\n",
978             dev->print_name(), jcr->JobId);
979          /* OK, compatible device */
980          return 1;
981       } else {
982          /* Drive Pool not suitable for us */
983          Mmsg(jcr->errmsg, _("3609 JobId=%u wants Pool=\"%s\" but have Pool=\"%s\" on drive %s.\n"), 
984                jcr->JobId, dcr->pool_name, dev->pool_name, dev->print_name());
985          queue_reserve_message(jcr);
986          Dmsg2(110, "failed: busy num_writers>0, can_append, pool=%s wanted=%s\n",
987             dev->pool_name, dcr->pool_name);
988          return 0;                    /* wait */
989       }
990    } else {
991       Pmsg0(000, _("Logic error!!!! Should not get here.\n"));
992       Mmsg(jcr->errmsg, _("3910 JobId=%u Logic error!!!! drive %s Should not get here.\n"),
993             jcr->JobId, dev->print_name());
994       queue_reserve_message(jcr);
995       Jmsg0(jcr, M_FATAL, 0, _("Logic error!!!! Should not get here.\n"));
996       return -1;                      /* error, should not get here */
997    }
998    Mmsg(jcr->errmsg, _("3911 JobId=%u failed reserve drive %s.\n"), 
999          jcr->JobId, dev->print_name());
1000    queue_reserve_message(jcr);
1001    Dmsg2(110, "failed: No reserve %s JobId=%u\n", dev->print_name(), jcr->JobId);
1002    return 0;
1003 }
1004
1005 /*
1006  * search_lock is already set on entering this routine 
1007  */
1008 static void queue_reserve_message(JCR *jcr)
1009 {
1010    int i;   
1011    alist *msgs = jcr->reserve_msgs;
1012    char *msg;
1013
1014    if (!msgs) {
1015       return;
1016    }
1017    /*
1018     * Look for duplicate message.  If found, do
1019     * not insert
1020     */
1021    for (i=msgs->size()-1; i >= 0; i--) {
1022       msg = (char *)msgs->get(i);
1023       if (!msg) {
1024          return;
1025       }
1026       /* Comparison based on 4 digit message number */
1027       if (strncmp(msg, jcr->errmsg, 4) == 0) {
1028          return;
1029       }
1030    }      
1031    /* Message unique, so insert it */
1032    jcr->reserve_msgs->push(bstrdup(jcr->errmsg));
1033 }
1034
1035 /*
1036  * Send any reservation messages queued for this jcr
1037  */
1038 void send_drive_reserve_messages(JCR *jcr, BSOCK *user)
1039 {
1040    int i;
1041    alist *msgs;
1042    char *msg;
1043
1044    lock_reservations();
1045    msgs = jcr->reserve_msgs;
1046    if (!msgs || msgs->size() == 0) {
1047       unlock_reservations();
1048       return;
1049    }
1050    for (i=msgs->size()-1; i >= 0; i--) {
1051       msg = (char *)msgs->get(i);
1052       if (msg) {
1053          bnet_fsend(user, "   %s", msg);
1054       } else {
1055          break;
1056       }
1057    }
1058    unlock_reservations();
1059 }