]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/reserve.c
d10c0c04271e2cbf24aa0f79302e449d1bec7980
[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    alist *dirstore;
344
345    memset(&rctx, 0, sizeof(RCTX));
346    rctx.jcr = jcr;
347    /*
348     * If there are multiple devices, the director sends us
349     *   use_device for each device that it wants to use.
350     */
351    dirstore = New(alist(10, not_owned_by_alist));
352 // Dmsg2(000, "dirstore=%p JobId=%u\n", dirstore, jcr->JobId);
353    msgs = jcr->reserve_msgs = New(alist(10, not_owned_by_alist));  
354    do {
355       Dmsg1(100, "<dird: %s", dir->msg);
356       ok = sscanf(dir->msg, use_storage, store_name.c_str(), 
357                   media_type.c_str(), pool_name.c_str(), 
358                   pool_type.c_str(), &append, &Copy, &Stripe) == 7;
359       if (!ok) {
360          break;
361       }
362       if (append) {
363          jcr->write_store = dirstore;
364       } else {
365          jcr->read_store = dirstore;
366       }
367       rctx.append = append;
368       unbash_spaces(store_name);
369       unbash_spaces(media_type);
370       unbash_spaces(pool_name);
371       unbash_spaces(pool_type);
372       store = new DIRSTORE;
373       dirstore->append(store);
374       memset(store, 0, sizeof(DIRSTORE));
375       store->device = New(alist(10));
376       bstrncpy(store->name, store_name, sizeof(store->name));
377       bstrncpy(store->media_type, media_type, sizeof(store->media_type));
378       bstrncpy(store->pool_name, pool_name, sizeof(store->pool_name));
379       bstrncpy(store->pool_type, pool_type, sizeof(store->pool_type));
380       store->append = append;
381
382       /* Now get all devices */
383       while (bnet_recv(dir) >= 0) {
384          Dmsg1(100, "<dird device: %s", dir->msg);
385          ok = sscanf(dir->msg, use_device, dev_name.c_str()) == 1;
386          if (!ok) {
387             break;
388          }
389          unbash_spaces(dev_name);
390          store->device->append(bstrdup(dev_name.c_str()));
391       }
392    }  while (ok && bnet_recv(dir) >= 0);
393
394 #ifdef DEVELOPER
395    /* This loop is debug code and can be removed */
396    /* ***FIXME**** remove after 1.38 release */
397    char *device_name;
398    foreach_alist(store, dirstore) {
399       Dmsg5(110, "Storage=%s media_type=%s pool=%s pool_type=%s append=%d\n", 
400          store->name, store->media_type, store->pool_name, 
401          store->pool_type, store->append);
402       foreach_alist(device_name, store->device) {
403          Dmsg1(110, "   Device=%s\n", device_name);
404       }
405    }
406 #endif
407
408    init_jcr_device_wait_timers(jcr);
409    /*                    
410     * At this point, we have a list of all the Director's Storage
411     *  resources indicated for this Job, which include Pool, PoolType,
412     *  storage name, and Media type.     
413     * Then for each of the Storage resources, we have a list of
414     *  device names that were given.
415     *
416     * Wiffle through them and find one that can do the backup.
417     */
418    if (ok) {
419       bool first = true;           /* print wait message once */
420       bool fail = false;
421       rctx.notify_dir = true;
422       lock_reservations();
423       for ( ; !fail && !job_canceled(jcr); ) {
424          while ((msg = (char *)msgs->pop())) {
425             free(msg);
426          }
427          rctx.suitable_device = false;
428          rctx.have_volume = false;
429          rctx.any_drive = false;
430          if (!jcr->PreferMountedVols) {
431             /* Look for unused drives in autochangers */
432             rctx.num_writers = 20000000;   /* start with impossible number */
433             rctx.low_use_drive = NULL;
434             rctx.PreferMountedVols = false;                
435             rctx.exact_match = false;
436             rctx.autochanger_only = true;
437             Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
438                rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
439                rctx.autochanger_only, rctx.any_drive);
440             if ((ok = find_suitable_device_for_job(jcr, rctx))) {
441                break;
442             }
443             /* Look through all drives possibly for low_use drive */
444             if (rctx.low_use_drive) {
445                rctx.try_low_use_drive = true;
446                if ((ok = find_suitable_device_for_job(jcr, rctx))) {
447                   break;
448                }
449                rctx.try_low_use_drive = false;
450             }
451             rctx.autochanger_only = false;
452             Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
453                rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
454                rctx.autochanger_only, rctx.any_drive);
455             if ((ok = find_suitable_device_for_job(jcr, rctx))) {
456                break;
457             }
458          }
459          /* Look for an exact match all drives */
460          rctx.PreferMountedVols = true;
461          rctx.exact_match = true;
462          rctx.autochanger_only = false;
463          Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
464             rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
465             rctx.autochanger_only, rctx.any_drive);
466          if ((ok = find_suitable_device_for_job(jcr, rctx))) {
467             break;
468          }
469          /* Look for any mounted drive */
470          rctx.exact_match = false;
471          Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
472             rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
473             rctx.autochanger_only, rctx.any_drive);
474          if ((ok = find_suitable_device_for_job(jcr, rctx))) {
475             break;
476          }
477          /* Try any drive */
478          rctx.any_drive = true;
479          Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
480             rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
481             rctx.autochanger_only, rctx.any_drive);
482          if ((ok = find_suitable_device_for_job(jcr, rctx))) {
483             break;
484          }
485          /* Keep reservations locked *except* during wait_for_device() */
486          unlock_reservations();
487          if (!rctx.suitable_device || !wait_for_device(jcr, first)) {
488             Dmsg0(100, "Fail. !suitable_device || !wait_for_device\n");
489             fail = true;
490          }   
491          lock_reservations();
492          first = false;
493          bnet_sig(dir, BNET_HEARTBEAT);  /* Inform Dir that we are alive */
494       }
495       unlock_reservations();
496       if (!ok) {
497          /*
498           * If we get here, there are no suitable devices available, which
499           *  means nothing configured.  If a device is suitable but busy
500           *  with another Volume, we will not come here.
501           */
502          unbash_spaces(dir->msg);
503          pm_strcpy(jcr->errmsg, dir->msg);
504          Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
505          Jmsg(jcr, M_FATAL, 0, _("\n"
506             "     Device \"%s\" with MediaType \"%s\" requested by DIR not found in SD Device resources.\n"),
507               dev_name.c_str(), media_type.c_str());
508          bnet_fsend(dir, NO_device, dev_name.c_str());
509
510          Dmsg1(100, ">dird: %s", dir->msg);
511       }
512    } else {
513       unbash_spaces(dir->msg);
514       pm_strcpy(jcr->errmsg, dir->msg);
515       Jmsg(jcr, M_FATAL, 0, _("Failed command: %s\n"), jcr->errmsg);
516       bnet_fsend(dir, BAD_use, jcr->errmsg);
517       Dmsg1(100, ">dird: %s", dir->msg);
518    }
519
520    release_msgs(jcr);
521    return ok;
522 }
523
524 void release_msgs(JCR *jcr)
525 {
526    alist *msgs = jcr->reserve_msgs;
527    char *msg;
528
529    if (!msgs) {
530       return;
531    }
532    lock_reservations();
533    while ((msg = (char *)msgs->pop())) {
534       free(msg);
535    }
536    delete msgs;
537    jcr->reserve_msgs = NULL;
538    unlock_reservations();
539 }
540
541 /*
542  * Search for a device suitable for this job.
543  */
544 bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx)
545 {
546    bool ok;
547    DIRSTORE *store;
548    char *device_name;
549    alist *dirstore;
550
551    if (rctx.append) {
552       dirstore = jcr->write_store;
553    } else {
554       dirstore = jcr->read_store;
555    }
556    /* 
557     * For each storage device that the user specified, we
558     *  search and see if there is a resource for that device.
559     */
560    Dmsg4(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d\n",
561       rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
562       rctx.autochanger_only);
563    ok = false;
564    foreach_alist(store, dirstore) {
565       rctx.store = store;
566       foreach_alist(device_name, store->device) {
567          int stat;
568          rctx.device_name = device_name;
569          stat = search_res_for_device(rctx); 
570          if (stat == 1) {             /* found available device */
571             Dmsg1(100, "Suitable device found=%s\n", device_name);
572             ok = true;
573             break;
574          } else if (stat == 0) {      /* device busy */
575             Dmsg1(110, "Suitable device found=%s, not used: busy\n", device_name);
576          } else {
577             /* otherwise error */
578             Dmsg0(110, "No suitable device found.\n");
579          }
580       }
581       if (ok) {
582          break;
583       }
584    }
585
586    return ok;
587 }
588
589 /*
590  * Search for a particular storage device with particular storage
591  *  characteristics (MediaType).
592  */
593 int search_res_for_device(RCTX &rctx) 
594 {
595    AUTOCHANGER *changer;
596    BSOCK *dir = rctx.jcr->dir_bsock;
597    bool ok;
598    int stat;
599
600    Dmsg1(110, "Search res for %s\n", rctx.device_name);
601    /* Look through Autochangers first */
602    foreach_res(changer, R_AUTOCHANGER) {
603       Dmsg1(150, "Try match changer res=%s\n", changer->hdr.name);
604       /* Find resource, and make sure we were able to open it */
605       if (fnmatch(rctx.device_name, changer->hdr.name, 0) == 0) {
606          /* Try each device in this AutoChanger */
607          foreach_alist(rctx.device, changer->device) {
608             Dmsg1(110, "Try changer device %s\n", rctx.device->hdr.name);
609             stat = reserve_device(rctx);
610             if (stat != 1) {             /* try another device */
611                continue;
612             }
613             POOL_MEM dev_name;
614             if (rctx.store->append == SD_APPEND) {
615                Dmsg2(100, "Device %s reserved=%d for append.\n", rctx.device->hdr.name,
616                   rctx.jcr->dcr->dev->reserved_device);
617             } else {
618                Dmsg2(100, "Device %s reserved=%d for read.\n", rctx.device->hdr.name,
619                   rctx.jcr->read_dcr->dev->reserved_device);
620             }
621             if (rctx.notify_dir) {
622                pm_strcpy(dev_name, rctx.device->hdr.name);
623                bash_spaces(dev_name);
624                ok = bnet_fsend(dir, OK_device, dev_name.c_str());  /* Return real device name */
625                Dmsg1(100, ">dird changer: %s", dir->msg);
626             } else {
627                ok = true;
628             }
629             return ok ? 1 : -1;
630          }
631       }
632    }
633
634    /* Now if requested look through regular devices */
635    if (!rctx.autochanger_only) {
636       foreach_res(rctx.device, R_DEVICE) {
637          Dmsg1(150, "Try match res=%s\n", rctx.device->hdr.name);
638          /* Find resource, and make sure we were able to open it */
639          if (fnmatch(rctx.device_name, rctx.device->hdr.name, 0) == 0) {
640             stat = reserve_device(rctx);
641             if (stat != 1) {
642                return stat;
643             }
644             if (rctx.notify_dir) {
645                bash_spaces(rctx.device_name);
646                ok = bnet_fsend(dir, OK_device, rctx.device_name);
647                Dmsg1(100, ">dird dev: %s", dir->msg);
648             } else {
649                ok = true;
650             }
651             return ok ? 1 : -1;
652          }
653       }
654    }
655    return -1;                    /* nothing found */
656 }
657
658 /*
659  *  Try to reserve a specific device.
660  *
661  *  Returns: 1 -- OK, have DCR
662  *           0 -- must wait
663  *          -1 -- fatal error
664  */
665 static int reserve_device(RCTX &rctx)
666 {
667    bool ok;
668    DCR *dcr;
669    const int name_len = MAX_NAME_LENGTH;
670
671    /* Make sure MediaType is OK */
672    Dmsg2(110, "MediaType device=%s request=%s\n",
673          rctx.device->media_type, rctx.store->media_type);
674    if (strcmp(rctx.device->media_type, rctx.store->media_type) != 0) {
675       return -1;
676    }
677
678    /* Make sure device exists -- i.e. we can stat() it */
679    if (!rctx.device->dev) {
680       rctx.device->dev = init_dev(rctx.jcr, rctx.device);
681    }
682    if (!rctx.device->dev) {
683       if (rctx.device->changer_res) {
684         Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
685            "     Device \"%s\" in changer \"%s\" requested by DIR could not be opened or does not exist.\n"),
686              rctx.device->hdr.name, rctx.device_name);
687       } else {
688          Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
689             "     Device \"%s\" requested by DIR could not be opened or does not exist.\n"),
690               rctx.device_name);
691       }
692       return -1;  /* no use waiting */
693    }  
694
695    rctx.suitable_device = true;
696    Dmsg2(110, "Try reserve %s JobId=%u\n", rctx.device->hdr.name,
697          rctx.jcr->JobId);
698    dcr = new_dcr(rctx.jcr, rctx.device->dev);
699    if (!dcr) {
700       BSOCK *dir = rctx.jcr->dir_bsock;
701       bnet_fsend(dir, _("3926 Could not get dcr for device: %s\n"), rctx.device_name);
702       Dmsg1(100, ">dird: %s", dir->msg);
703       return -1;
704    }
705    bstrncpy(dcr->pool_name, rctx.store->pool_name, name_len);
706    bstrncpy(dcr->pool_type, rctx.store->pool_type, name_len);
707    bstrncpy(dcr->media_type, rctx.store->media_type, name_len);
708    bstrncpy(dcr->dev_name, rctx.device_name, name_len);
709    if (rctx.store->append == SD_APPEND) {
710       if (rctx.exact_match && !rctx.have_volume) {
711          dcr->any_volume = true;
712          if (dir_find_next_appendable_volume(dcr)) {
713             bstrncpy(rctx.VolumeName, dcr->VolumeName, sizeof(rctx.VolumeName));
714             Dmsg2(100, "JobId=%u looking for Volume=%s\n", rctx.jcr->JobId, rctx.VolumeName);
715             rctx.have_volume = true;
716          } else {
717             Dmsg0(100, "No next volume found\n");
718             rctx.VolumeName[0] = 0;
719         }
720       }
721       ok = reserve_device_for_append(dcr, rctx);
722       if (ok) {
723          rctx.jcr->dcr = dcr;
724          Dmsg5(100, "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    } else {
729       ok = reserve_device_for_read(dcr);
730       if (ok) {
731          rctx.jcr->read_dcr = dcr;
732          Dmsg5(100, "Read reserved=%d dev_name=%s mediatype=%s pool=%s ok=%d\n",
733                dcr->dev->reserved_device,
734                dcr->dev_name, dcr->media_type, dcr->pool_name, ok);
735       }
736    }
737    if (!ok) {
738       free_dcr(dcr);
739       Dmsg0(110, "Not OK.\n");
740       return 0;
741    }
742    return 1;
743 }
744
745 /*
746  * We "reserve" the drive by setting the ST_READ bit. No one else
747  *  should touch the drive until that is cleared.
748  *  This allows the DIR to "reserve" the device before actually
749  *  starting the job. 
750  */
751 static bool reserve_device_for_read(DCR *dcr)
752 {
753    DEVICE *dev = dcr->dev;
754    JCR *jcr = dcr->jcr;
755    bool ok = false;
756
757    ASSERT(dcr);
758
759    /* Get locks in correct order */
760    unlock_reservations();
761    P(dev->mutex);
762    lock_reservations();
763
764    if (is_device_unmounted(dev)) {             
765       Dmsg1(200, "Device %s is BLOCKED due to user unmount.\n", dev->print_name());
766       Mmsg(jcr->errmsg, _("3601 JobId=%u device %s is BLOCKED due to user unmount.\n"),
767            jcr->JobId, dev->print_name());
768       queue_reserve_message(jcr);
769       goto bail_out;
770    }
771
772    if (dev->is_busy()) {
773       Dmsg4(200, "Device %s is busy ST_READ=%d num_writers=%d reserved=%d.\n", dev->print_name(),
774          dev->state & ST_READ?1:0, dev->num_writers, dev->reserved_device);
775       Mmsg(jcr->errmsg, _("3602 JobId=%u device %s is busy (already reading/writing).\n"),
776             jcr->JobId, dev->print_name());
777       queue_reserve_message(jcr);
778       goto bail_out;
779    }
780
781    dev->clear_append();
782    dev->set_read();
783    ok = true;
784    dev->reserved_device++;
785    Dmsg3(100, "Inc reserve=%d dev=%s %p\n", dev->reserved_device, 
786       dev->print_name(), dev);
787    dcr->reserved_device = true;
788
789 bail_out:
790    V(dev->mutex);
791    return ok;
792 }
793
794
795 /*
796  * We reserve the device for appending by incrementing the 
797  *  reserved_device. We do virtually all the same work that
798  *  is done in acquire_device_for_append(), but we do
799  *  not attempt to mount the device. This routine allows
800  *  the DIR to reserve multiple devices before *really* 
801  *  starting the job. It also permits the SD to refuse 
802  *  certain devices (not up, ...).
803  *
804  * Note, in reserving a device, if the device is for the
805  *  same pool and the same pool type, then it is acceptable.
806  *  The Media Type has already been checked. If we are
807  *  the first tor reserve the device, we put the pool
808  *  name and pool type in the device record.
809  */
810 static bool reserve_device_for_append(DCR *dcr, RCTX &rctx)
811 {
812    JCR *jcr = dcr->jcr;
813    DEVICE *dev = dcr->dev;
814    bool ok = false;
815
816    ASSERT(dcr);
817
818    P(dev->mutex);
819
820    /* If device is being read, we cannot write it */
821    if (dev->can_read()) {
822       Mmsg(jcr->errmsg, _("3603 JobId=%u device %s is busy reading.\n"), 
823          jcr->JobId, dev->print_name());
824       Dmsg1(110, "%s", jcr->errmsg);
825       queue_reserve_message(jcr);
826       goto bail_out;
827    }
828
829    /* If device is unmounted, we are out of luck */
830    if (is_device_unmounted(dev)) {
831       Mmsg(jcr->errmsg, _("3604 JobId=%u device %s is BLOCKED due to user unmount.\n"), 
832          jcr->JobId, dev->print_name());
833       Dmsg1(110, "%s", jcr->errmsg);
834       queue_reserve_message(jcr);
835       goto bail_out;
836    }
837
838    Dmsg1(110, "reserve_append device is %s\n", dev->is_tape()?"tape":"disk");
839
840    /* Now do detailed tests ... */
841    if (can_reserve_drive(dcr, rctx) != 1) {
842       Dmsg0(110, "can_reserve_drive!=1\n");
843       goto bail_out;
844    }
845
846    dev->reserved_device++;
847    Dmsg3(100, "Inc reserve=%d dev=%s %p\n", dev->reserved_device, 
848       dev->print_name(), dev);
849    dcr->reserved_device = true;
850    ok = true;
851
852 bail_out:
853    V(dev->mutex);
854    return ok;
855 }
856
857 /*
858  * Returns: 1 if drive can be reserved
859  *          0 if we should wait
860  *         -1 on error or impossibility
861  */
862 static int can_reserve_drive(DCR *dcr, RCTX &rctx) 
863 {
864    DEVICE *dev = dcr->dev;
865    JCR *jcr = dcr->jcr;
866
867    Dmsg5(110, "PrefMnt=%d exact=%d suitable=%d chgronly=%d any=%d\n",
868          rctx.PreferMountedVols, rctx.exact_match, rctx.suitable_device,
869          rctx.autochanger_only, rctx.any_drive);
870
871    /* setting any_drive overrides PreferMountedVols flag */
872    if (!rctx.any_drive) {
873       /*
874        * When PreferMountedVols is set, we keep track of the 
875        *  drive in use that has the least number of writers, then if
876        *  no unmounted drive is found, we try that drive. This   
877        *  helps spread the load to the least used drives.  
878        */
879       if (rctx.try_low_use_drive && dev == rctx.low_use_drive) {
880          Dmsg3(110, "OK dev=%s == low_drive=%s. JobId=%u\n",
881             dev->print_name(), rctx.low_use_drive->print_name(), jcr->JobId);
882          return 1;
883       }
884       /* If he wants a free drive, but this one is busy, no go */
885       if (!rctx.PreferMountedVols && dev->is_busy()) {
886          /* Save least used drive */
887          if ((dev->num_writers + dev->reserved_device) < rctx.num_writers) {
888             rctx.num_writers = dev->num_writers + dev->reserved_device;
889             rctx.low_use_drive = dev;
890             Dmsg2(110, "set low use drive=%s num_writers=%d\n", dev->print_name(),
891                rctx.num_writers);
892          } else {
893             Dmsg1(110, "not low use num_writers=%d\n", dev->num_writers+ 
894                dev->reserved_device);
895          }
896          Dmsg1(110, "failed: !prefMnt && busy. JobId=%u\n", jcr->JobId);
897          Mmsg(jcr->errmsg, _("3605 JobId=%u wants free drive but device %s is busy.\n"), 
898             jcr->JobId, dev->print_name());
899          queue_reserve_message(jcr);
900          return 0;
901       }
902
903       /* Check for prefer mounted volumes */
904       if (rctx.PreferMountedVols && !dev->VolHdr.VolumeName[0] && dev->is_tape()) {
905          Mmsg(jcr->errmsg, _("3606 JobId=%u wants mounted, but drive %s has no Volume.\n"), 
906             jcr->JobId, dev->print_name());
907          queue_reserve_message(jcr);
908          Dmsg1(110, "failed: want mounted -- no vol JobId=%u\n", jcr->JobId);
909          return 0;                 /* No volume mounted */
910       }
911
912       /* Check for exact Volume name match */
913       if (rctx.exact_match && rctx.have_volume &&
914           strcmp(dev->VolHdr.VolumeName, rctx.VolumeName) != 0) {
915          Mmsg(jcr->errmsg, _("3607 JobId=%u wants Vol=\"%s\" drive has Vol=\"%s\" on drive %s.\n"), 
916             jcr->JobId, rctx.VolumeName, dev->VolHdr.VolumeName, 
917             dev->print_name());
918          queue_reserve_message(jcr);
919          Dmsg2(110, "failed: Not exact match have=%s want=%s\n",
920                dev->VolHdr.VolumeName, rctx.VolumeName);
921          return 0;
922       }
923    }
924
925    /* Check for unused autochanger drive */
926    if (rctx.autochanger_only && dev->num_writers == 0 &&
927        dev->VolHdr.VolumeName[0] == 0) {
928       /* Device is available but not yet reserved, reserve it for us */
929       Dmsg2(100, "OK Res Unused autochanger %s JobId=%u.\n",
930          dev->print_name(), jcr->JobId);
931       bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
932       bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
933       return 1;                       /* reserve drive */
934    }
935
936    /*
937     * Handle the case that there are no writers
938     */
939    if (dev->num_writers == 0) {
940       /* Now check if there are any reservations on the drive */
941       if (dev->reserved_device) {           
942          /* Now check if we want the same Pool and pool type */
943          if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
944              strcmp(dev->pool_type, dcr->pool_type) == 0) {
945             /* OK, compatible device */
946             Dmsg2(100, "OK dev: %s num_writers=0, reserved, pool matches JobId=%u\n",
947                dev->print_name(), jcr->JobId);
948             return 1;
949          } else {
950             /* Drive Pool not suitable for us */
951             Mmsg(jcr->errmsg, _("3608 JobId=%u wants Pool=\"%s\" but have Pool=\"%s\" on drive %s.\n"), 
952                   jcr->JobId, dcr->pool_name, dev->pool_name, dev->print_name());
953             queue_reserve_message(jcr);
954             Dmsg2(110, "failed: busy num_writers=0, reserved, pool=%s wanted=%s\n",
955                dev->pool_name, dcr->pool_name);
956             return 0;                 /* wait */
957          }
958       } else if (dev->can_append()) {
959          /* Device in append mode, check if changing pool */
960          if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
961              strcmp(dev->pool_type, dcr->pool_type) == 0) {
962             Dmsg2(100, "OK dev: %s num_writers=0, can_append, pool matches. JobId=%u\n",
963                dev->print_name(), jcr->JobId);
964             /* OK, compatible device */
965             return 1;
966          } else {
967             /* Changing pool, unload old tape if any in drive */
968             Dmsg0(100, "OK dev: num_writers=0, not reserved, pool change, unload changer\n");
969             unload_autochanger(dcr, 0);
970          }
971       }
972       /* Device is available but not yet reserved, reserve it for us */
973       Dmsg2(100, "OK Dev avail reserved %s JobId=%u\n", dev->print_name(),
974          jcr->JobId);
975       bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
976       bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
977       return 1;                       /* reserve drive */
978    }
979
980    /*
981     * Check if the device is in append mode with writers (i.e.
982     *  available if pool is the same).
983     */
984    if (dev->can_append() || dev->num_writers > 0) {
985       /* Yes, now check if we want the same Pool and pool type */
986       if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
987           strcmp(dev->pool_type, dcr->pool_type) == 0) {
988          Dmsg2(100, "OK dev: %s num_writers>=0, can_append, pool matches. JobId=%u\n",
989             dev->print_name(), jcr->JobId);
990          /* OK, compatible device */
991          return 1;
992       } else {
993          /* Drive Pool not suitable for us */
994          Mmsg(jcr->errmsg, _("3609 JobId=%u wants Pool=\"%s\" but have Pool=\"%s\" on drive %s.\n"), 
995                jcr->JobId, dcr->pool_name, dev->pool_name, dev->print_name());
996          queue_reserve_message(jcr);
997          Dmsg2(110, "failed: busy num_writers>0, can_append, pool=%s wanted=%s\n",
998             dev->pool_name, dcr->pool_name);
999          return 0;                    /* wait */
1000       }
1001    } else {
1002       Pmsg0(000, _("Logic error!!!! Should not get here.\n"));
1003       Mmsg(jcr->errmsg, _("3910 JobId=%u Logic error!!!! drive %s Should not get here.\n"),
1004             jcr->JobId, dev->print_name());
1005       queue_reserve_message(jcr);
1006       Jmsg0(jcr, M_FATAL, 0, _("Logic error!!!! Should not get here.\n"));
1007       return -1;                      /* error, should not get here */
1008    }
1009    Mmsg(jcr->errmsg, _("3911 JobId=%u failed reserve drive %s.\n"), 
1010          jcr->JobId, dev->print_name());
1011    queue_reserve_message(jcr);
1012    Dmsg2(110, "failed: No reserve %s JobId=%u\n", dev->print_name(), jcr->JobId);
1013    return 0;
1014 }
1015
1016 /*
1017  * search_lock is already set on entering this routine 
1018  */
1019 static void queue_reserve_message(JCR *jcr)
1020 {
1021    int i;   
1022    alist *msgs = jcr->reserve_msgs;
1023    char *msg;
1024
1025    if (!msgs) {
1026       return;
1027    }
1028    /*
1029     * Look for duplicate message.  If found, do
1030     * not insert
1031     */
1032    for (i=msgs->size()-1; i >= 0; i--) {
1033       msg = (char *)msgs->get(i);
1034       if (!msg) {
1035          return;
1036       }
1037       /* Comparison based on 4 digit message number */
1038       if (strncmp(msg, jcr->errmsg, 4) == 0) {
1039          return;
1040       }
1041    }      
1042    /* Message unique, so insert it */
1043    jcr->reserve_msgs->push(bstrdup(jcr->errmsg));
1044 }
1045
1046 /*
1047  * Send any reservation messages queued for this jcr
1048  */
1049 void send_drive_reserve_messages(JCR *jcr, BSOCK *user)
1050 {
1051    int i;
1052    alist *msgs;
1053    char *msg;
1054
1055    lock_reservations();
1056    msgs = jcr->reserve_msgs;
1057    if (!msgs || msgs->size() == 0) {
1058       unlock_reservations();
1059       return;
1060    }
1061    for (i=msgs->size()-1; i >= 0; i--) {
1062       msg = (char *)msgs->get(i);
1063       if (msg) {
1064          bnet_fsend(user, "   %s", msg);
1065       } else {
1066          break;
1067       }
1068    }
1069    unlock_reservations();
1070 }