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