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