]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/stored/reserve.c
- Create unload_autochanger() subroutine, and unload
[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-2005 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  *   Use Device command from Director
31  *   He tells is what Device Name to use, the Media Type,
32  *      the Pool Name, and the Pool Type.
33  *
34  *    Ensure that the device exists and is opened, then store
35  *      the media and pool info in the JCR.  This class is used
36  *      only temporarily in this file.
37  */
38 class DIRSTORE {
39 public:
40    alist *device;
41    bool append;
42    char name[MAX_NAME_LENGTH];
43    char media_type[MAX_NAME_LENGTH];
44    char pool_name[MAX_NAME_LENGTH];
45    char pool_type[MAX_NAME_LENGTH];
46 };
47
48 /* Reserve context */
49 class RCTX {
50 public:
51    alist *errors;
52    JCR *jcr;
53    char *device_name;
54    DIRSTORE *store;
55    DEVRES   *device;
56    bool PreferMountedVols;
57 };
58
59 static dlist *vol_list = NULL;
60 static pthread_mutex_t vol_list_lock = PTHREAD_MUTEX_INITIALIZER;
61 static pthread_mutex_t search_lock = PTHREAD_MUTEX_INITIALIZER;
62
63 /* Forward referenced functions */
64 static int can_reserve_drive(DCR *dcr, bool PerferMountedVols);
65 static int search_res_for_device(RCTX &rctx);
66 static int reserve_device(RCTX &rctx);
67 static bool reserve_device_for_read(DCR *dcr);
68 static bool reserve_device_for_append(DCR *dcr, bool PreferMountedVols);
69 static bool use_storage_cmd(JCR *jcr);
70 bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx);
71
72 /* Requests from the Director daemon */
73 static char use_storage[]  = "use storage=%127s media_type=%127s "
74    "pool_name=%127s pool_type=%127s append=%d copy=%d stripe=%d\n";
75 static char use_device[]  = "use device=%127s\n";
76
77 /* Responses sent to Director daemon */
78 static char OK_device[] = "3000 OK use device device=%s\n";
79 static char NO_device[] = "3924 Device \"%s\" not in SD Device resources.\n";
80 static char BAD_use[]   = "3913 Bad use command: %s\n";
81
82 bool use_cmd(JCR *jcr) 
83 {
84    /*
85     * Get the device, media, and pool information
86     */
87    if (!use_storage_cmd(jcr)) {
88       set_jcr_job_status(jcr, JS_ErrorTerminated);
89       memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
90       return false;
91    }
92    return true;
93 }
94
95 static int my_compare(void *item1, void *item2)
96 {
97    return strcmp(((VOLRES *)item1)->vol_name, ((VOLRES *)item2)->vol_name);
98 }
99
100
101 /*
102  * Put a new Volume entry in the Volume list. This
103  *  effectively reserves the volume so that it will
104  *  not be mounted again.
105  *
106  *  Return: VOLRES entry on success
107  *          NULL if the Volume is already in the list
108  */
109 VOLRES *new_volume(DCR *dcr, const char *VolumeName)
110 {
111    VOLRES *vol, *nvol;
112
113    Dmsg1(400, "new_volume %s\n", VolumeName);
114    vol = (VOLRES *)malloc(sizeof(VOLRES));
115    memset(vol, 0, sizeof(VOLRES));
116    vol->vol_name = bstrdup(VolumeName);
117    vol->dev = dcr->dev;
118    vol->dcr = dcr;
119    P(vol_list_lock);
120    nvol = (VOLRES *)vol_list->binary_insert(vol, my_compare);
121    V(vol_list_lock);
122    if (nvol != vol) {
123       free(vol->vol_name);
124       free(vol);
125       if (dcr->dev) {
126          nvol->dev = dcr->dev;
127       }
128       return NULL;
129    }
130    return vol;
131 }
132
133 /*
134  * Search for a Volume name in the Volume list.
135  *
136  *  Returns: VOLRES entry on success
137  *           NULL if the Volume is not in the list
138  */
139 VOLRES *find_volume(const char *VolumeName)
140 {
141    VOLRES vol, *fvol;
142    vol.vol_name = bstrdup(VolumeName);
143    P(vol_list_lock);
144    fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
145    V(vol_list_lock);
146    free(vol.vol_name);
147    return fvol;
148 }
149
150 /*  
151  * Free a Volume from the Volume list
152  *
153  *  Returns: true if the Volume found and removed from the list
154  *           false if the Volume is not in the list
155  */
156 bool free_volume(DEVICE *dev)
157 {
158    VOLRES vol, *fvol;
159
160    if (dev->VolHdr.VolumeName[0] == 0) {
161       return false;
162    }
163    Dmsg1(400, "free_volume %s\n", dev->VolHdr.VolumeName);
164    vol.vol_name = bstrdup(dev->VolHdr.VolumeName);
165    P(vol_list_lock);
166    fvol = (VOLRES *)vol_list->binary_search(&vol, my_compare);
167    if (fvol) {
168       vol_list->remove(fvol);
169       free(fvol->vol_name);
170       free(fvol);
171    }
172    V(vol_list_lock);
173    free(vol.vol_name);
174    dev->VolHdr.VolumeName[0] = 0;
175    return fvol != NULL;
176 }
177
178 /* Free volume reserved by this dcr but not attached to a dev */
179 void free_unused_volume(DCR *dcr)
180 {
181    VOLRES *vol;
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       bnet_fsend(user, "%s\n", vol->vol_name);
203    }
204 }
205       
206 /* Create the Volume list */
207 void create_volume_list()
208 {
209    VOLRES *dummy = NULL;
210    if (vol_list == NULL) {
211       vol_list = New(dlist(dummy, &dummy->link));
212    }
213 }
214
215 /* Release all Volumes from the list */
216 void free_volume_list()
217 {
218    VOLRES *vol;
219    if (!vol_list) {
220       return;
221    }
222    for (vol=(VOLRES *)vol_list->first(); vol; vol=(VOLRES *)vol_list->next(vol)) {
223       Dmsg3(000, "Unreleased Volume=%s dcr=0x%x dev=0x%x\n", vol->vol_name,
224          vol->dcr, vol->dev);
225    }
226    delete vol_list;
227    vol_list = NULL;
228 }
229
230 bool is_volume_in_use(DCR *dcr)
231 {
232    VOLRES *vol = find_volume(dcr->VolumeName);
233    if (!vol) {
234       return false;                   /* vol not in list */
235    }
236    if (!vol->dev) {                   /* vol not attached to device */
237       return false;
238    }
239    if (dcr->dev == vol->dev) {        /* same device OK */
240       return false;
241    }
242    if (!vol->dev->is_busy()) {
243       return false;
244    }
245    return true;
246 }
247
248
249 static bool use_storage_cmd(JCR *jcr)
250 {
251    POOL_MEM store_name, dev_name, media_type, pool_name, pool_type;
252    BSOCK *dir = jcr->dir_bsock;
253    int append;
254    bool ok;       
255    int Copy, Stripe;
256    DIRSTORE *store;
257    RCTX rctx;
258 #ifdef implemented
259    char *error;
260 #endif
261
262    memset(&rctx, 0, sizeof(RCTX));
263    rctx.jcr = jcr;
264    /*
265     * If there are multiple devices, the director sends us
266     *   use_device for each device that it wants to use.
267     */
268    Dmsg1(100, "<dird: %s", dir->msg);
269    jcr->dirstore = New(alist(10, not_owned_by_alist));
270    do {
271       ok = sscanf(dir->msg, use_storage, store_name.c_str(), 
272                   media_type.c_str(), pool_name.c_str(), 
273                   pool_type.c_str(), &append, &Copy, &Stripe) == 7;
274       if (!ok) {
275          break;
276       }
277       unbash_spaces(store_name);
278       unbash_spaces(media_type);
279       unbash_spaces(pool_name);
280       unbash_spaces(pool_type);
281       store = new DIRSTORE;
282       jcr->dirstore->append(store);
283       memset(store, 0, sizeof(DIRSTORE));
284       store->device = New(alist(10));
285       bstrncpy(store->name, store_name, sizeof(store->name));
286       bstrncpy(store->media_type, media_type, sizeof(store->media_type));
287       bstrncpy(store->pool_name, pool_name, sizeof(store->pool_name));
288       bstrncpy(store->pool_type, pool_type, sizeof(store->pool_type));
289       store->append = append;
290
291       /* Now get all devices */
292       while (bnet_recv(dir) >= 0) {
293          ok = sscanf(dir->msg, use_device, dev_name.c_str()) == 1;
294          if (!ok) {
295             break;
296          }
297          unbash_spaces(dev_name);
298          store->device->append(bstrdup(dev_name.c_str()));
299       }
300    }  while (ok && bnet_recv(dir) >= 0);
301
302 #ifdef DEVELOPER
303    /* This loop is debug code and can be removed */
304    /* ***FIXME**** remove after 1.38 release */
305    char *device_name;
306    foreach_alist(store, jcr->dirstore) {
307       Dmsg4(100, "Storage=%s media_type=%s pool=%s pool_type=%s\n", 
308          store->name, store->media_type, store->pool_name, 
309          store->pool_type);
310       foreach_alist(device_name, store->device) {
311          Dmsg1(100, "   Device=%s\n", device_name);
312       }
313    }
314 #endif
315
316    /*                    
317     * At this point, we have a list of all the Director's Storage
318     *  resources indicated for this Job, which include Pool, PoolType,
319     *  storage name, and Media type.     
320     * Then for each of the Storage resources, we have a list of
321     *  device names that were given.
322     *
323     * Wiffle through them and find one that can do the backup.
324     */
325    if (ok) {
326       /*
327        * Make up to two passes. The first with PreferMountedVols possibly
328        *   set to true.  In that case, we look only for an available 
329        *   drive with something mounted. If that fails, then we
330        *   do a second pass with PerferMountedVols set false.
331        */
332       rctx.PreferMountedVols = jcr->PreferMountedVols;
333       ok = find_suitable_device_for_job(jcr, rctx);
334       if (ok) {
335          goto done;
336       }
337       if (rctx.PreferMountedVols) {
338          rctx.PreferMountedVols = false;
339          ok = find_suitable_device_for_job(jcr, rctx);
340          if (ok) {
341             goto done;
342          }
343       }
344       if (verbose) {
345          unbash_spaces(dir->msg);
346          pm_strcpy(jcr->errmsg, dir->msg);
347          Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
348       }
349       Jmsg(jcr, M_FATAL, 0, _("\n"
350          "     Device \"%s\" with MediaType \"%s\" requested by DIR not found in SD Device resources.\n"),
351            dev_name.c_str(), media_type.c_str());
352       bnet_fsend(dir, NO_device, dev_name.c_str());
353 #ifdef implemented
354       for (error=(char*)rctx->errors.first(); error;
355            error=(char*)rctx->errors.next()) {
356          Jmsg(jcr, M_INFO, 0, "%s", error);
357       }
358 #endif
359       Dmsg1(100, ">dird: %s", dir->msg);
360    } else {
361       unbash_spaces(dir->msg);
362       pm_strcpy(jcr->errmsg, dir->msg);
363       if (verbose) {
364          Jmsg(jcr, M_INFO, 0, _("Failed command: %s\n"), jcr->errmsg);
365       }
366       bnet_fsend(dir, BAD_use, jcr->errmsg);
367       Dmsg1(100, ">dird: %s", dir->msg);
368    }
369
370 done:
371    foreach_alist(store, jcr->dirstore) {
372       delete store->device;
373       delete store;
374    }
375    delete jcr->dirstore;
376 #ifdef implemented
377    for (error=(char*)rctx->errors.first(); error;
378         error=(char*)rctx->errors.next()) {
379       free(error);
380    }
381 #endif
382    return ok;
383 }
384
385
386 /*
387  * Search for a device suitable for this job.
388  */
389 bool find_suitable_device_for_job(JCR *jcr, RCTX &rctx)
390 {
391    bool first = true;
392    bool ok;
393    DCR *dcr = NULL;
394    DIRSTORE *store;
395    char *device_name;
396
397    init_jcr_device_wait_timers(jcr);
398    for ( ;; ) {
399       int need_wait = false;
400       ok = false;
401       P(search_lock);
402       foreach_alist(store, jcr->dirstore) {
403          rctx.store = store;
404          foreach_alist(device_name, store->device) {
405             int stat;
406             rctx.device_name = device_name;
407             stat = search_res_for_device(rctx); 
408             if (stat == 1) {             /* found available device */
409                dcr = jcr->dcr;
410                ok = true;
411                break;
412             } else if (stat == 0) {      /* device busy */
413                need_wait = true;
414             }
415             /* otherwise error */
416 //             rctx->errors.push(bstrdup(jcr->errmsg));
417          }
418          if (ok) {
419             break;
420          }
421       }
422       V(search_lock);
423       /*
424        * If there is some device for which we can wait, then
425        *  wait and try again until the wait time expires
426        */
427       if (!need_wait || !wait_for_device(jcr, first)) {
428          break;
429       }
430       first = false;
431 #ifdef implemented
432       for (error=(char*)rctx->errors.first(); error;
433            error=(char*)rctx->errors.next()) {
434          free(error);
435       }
436 #endif
437    }
438    if (!ok && dcr) {
439       free_dcr(dcr);
440    }
441
442    return ok;
443 }
444
445 /*
446  * Search for a particular storage device with particular storage
447  *  characteristics (MediaType).
448  */
449 static int search_res_for_device(RCTX &rctx) 
450 {
451    AUTOCHANGER *changer;
452    BSOCK *dir = rctx.jcr->dir_bsock;
453    bool ok;
454    int stat;
455
456    Dmsg1(100, "Search res for %s\n", rctx.device_name);
457    foreach_res(rctx.device, R_DEVICE) {
458       Dmsg1(100, "Try res=%s\n", rctx.device->hdr.name);
459       /* Find resource, and make sure we were able to open it */
460       if (fnmatch(rctx.device_name, rctx.device->hdr.name, 0) == 0) {
461          stat = reserve_device(rctx);
462          if (stat != 1) {
463             return stat;
464          }
465          Dmsg1(220, "Got: %s", dir->msg);
466          bash_spaces(rctx.device_name);
467          ok = bnet_fsend(dir, OK_device, rctx.device_name);
468          Dmsg1(100, ">dird dev: %s", dir->msg);
469          return ok ? 1 : -1;
470       }
471    }
472    foreach_res(changer, R_AUTOCHANGER) {
473       Dmsg1(100, "Try changer res=%s\n", changer->hdr.name);
474       /* Find resource, and make sure we were able to open it */
475       if (fnmatch(rctx.device_name, changer->hdr.name, 0) == 0) {
476          /* Try each device in this AutoChanger */
477          foreach_alist(rctx.device, changer->device) {
478             Dmsg1(100, "Try changer device %s\n", rctx.device->hdr.name);
479             stat = reserve_device(rctx);
480             if (stat == -1) {            /* hard error */
481                return -1;
482             }
483             if (stat == 0) {             /* must wait, try next one */
484                continue;
485             }
486             POOL_MEM dev_name;
487             Dmsg1(100, "Device %s opened.\n", rctx.device_name);
488             pm_strcpy(dev_name, rctx.device->hdr.name);
489             bash_spaces(dev_name);
490             ok = bnet_fsend(dir, OK_device, dev_name.c_str());  /* Return real device name */
491             Dmsg1(100, ">dird changer: %s", dir->msg);
492             return ok ? 1 : -1;
493          }
494       }
495    }
496    return 0;                    /* nothing found */
497 }
498
499 /*
500  *  Try to reserve a specific device.
501  *
502  *  Returns: 1 -- OK, have DCR
503  *           0 -- must wait
504  *          -1 -- fatal error
505  */
506 static int reserve_device(RCTX &rctx)
507 {
508    bool ok;
509    DCR *dcr;
510    const int name_len = MAX_NAME_LENGTH;
511
512    /* Make sure MediaType is OK */
513    if (strcmp(rctx.device->media_type, rctx.store->media_type) != 0) {
514       return -1;
515    }
516
517    if (!rctx.device->dev) {
518       rctx.device->dev = init_dev(rctx.jcr, rctx.device);
519    }
520    if (!rctx.device->dev) {
521       if (rctx.device->changer_res) {
522         Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
523            "     Device \"%s\" in changer \"%s\" requested by DIR could not be opened or does not exist.\n"),
524              rctx.device->hdr.name, rctx.device_name);
525       } else {
526          Jmsg(rctx.jcr, M_WARNING, 0, _("\n"
527             "     Device \"%s\" requested by DIR could not be opened or does not exist.\n"),
528               rctx.device_name);
529       }
530       return -1;  /* no use waiting */
531    }  
532    Dmsg1(100, "Found device %s\n", rctx.device->hdr.name);
533    dcr = new_dcr(rctx.jcr, rctx.device->dev);
534    if (!dcr) {
535       BSOCK *dir = rctx.jcr->dir_bsock;
536       bnet_fsend(dir, _("3926 Could not get dcr for device: %s\n"), rctx.device_name);
537       Dmsg1(100, ">dird: %s", dir->msg);
538       return -1;
539    }
540    rctx.jcr->dcr = dcr;
541    bstrncpy(dcr->pool_name, rctx.store->pool_name, name_len);
542    bstrncpy(dcr->pool_type, rctx.store->pool_type, name_len);
543    bstrncpy(dcr->media_type, rctx.store->media_type, name_len);
544    bstrncpy(dcr->dev_name, rctx.device_name, name_len);
545    if (rctx.store->append == SD_APPEND) {
546       ok = reserve_device_for_append(dcr, rctx.PreferMountedVols);
547       Dmsg3(200, "dev_name=%s mediatype=%s ok=%d\n", dcr->dev_name, dcr->media_type, ok);
548    } else {
549       ok = reserve_device_for_read(dcr);
550    }
551    if (!ok) {
552       free_dcr(rctx.jcr->dcr);
553       return 0;
554    }
555    return 1;
556 }
557
558 /*
559  * We "reserve" the drive by setting the ST_READ bit. No one else
560  *  should touch the drive until that is cleared.
561  *  This allows the DIR to "reserve" the device before actually
562  *  starting the job. 
563  */
564 static bool reserve_device_for_read(DCR *dcr)
565 {
566    DEVICE *dev = dcr->dev;
567    JCR *jcr = dcr->jcr;
568    bool ok = false;
569
570    ASSERT(dcr);
571
572    dev->block(BST_DOING_ACQUIRE);
573
574    if (is_device_unmounted(dev)) {             
575       Dmsg1(200, "Device %s is BLOCKED due to user unmount.\n", dev->print_name());
576       Mmsg(jcr->errmsg, _("Device %s is BLOCKED due to user unmount.\n"),
577            dev->print_name());
578       goto bail_out;
579    }
580
581    if (dev->is_busy()) {
582       Dmsg4(200, "Device %s is busy ST_READ=%d num_writers=%d reserved=%d.\n", dev->print_name(),
583          dev->state & ST_READ?1:0, dev->num_writers, dev->reserved_device);
584       Mmsg1(jcr->errmsg, _("Device %s is busy.\n"),
585             dev->print_name());
586       goto bail_out;
587    }
588
589    dev->clear_append();
590    dev->set_read();
591    ok = true;
592
593 bail_out:
594    dev->unblock();
595    return ok;
596 }
597
598
599 /*
600  * We reserve the device for appending by incrementing the 
601  *  reserved_device. We do virtually all the same work that
602  *  is done in acquire_device_for_append(), but we do
603  *  not attempt to mount the device. This routine allows
604  *  the DIR to reserve multiple devices before *really* 
605  *  starting the job. It also permits the SD to refuse 
606  *  certain devices (not up, ...).
607  *
608  * Note, in reserving a device, if the device is for the
609  *  same pool and the same pool type, then it is acceptable.
610  *  The Media Type has already been checked. If we are
611  *  the first tor reserve the device, we put the pool
612  *  name and pool type in the device record.
613  */
614 static bool reserve_device_for_append(DCR *dcr, bool PreferMountedVols) 
615 {
616    JCR *jcr = dcr->jcr;
617    DEVICE *dev = dcr->dev;
618    bool ok = false;
619
620    ASSERT(dcr);
621
622    dev->block(BST_DOING_ACQUIRE);
623
624    if (dev->can_read()) {
625       Mmsg1(jcr->errmsg, _("Device %s is busy reading.\n"), dev->print_name());
626       Dmsg1(100, "%s", jcr->errmsg);
627       goto bail_out;
628    }
629
630    if (is_device_unmounted(dev)) {
631       Mmsg(jcr->errmsg, _("Device %s is BLOCKED due to user unmount.\n"), dev->print_name());
632       Dmsg1(100, "%s", jcr->errmsg);
633       goto bail_out;
634    }
635
636    Dmsg1(190, "reserve_append device is %s\n", dev->is_tape()?"tape":"disk");
637
638    if (can_reserve_drive(dcr, PreferMountedVols) != 1) {
639       Mmsg1(jcr->errmsg, _("Device %s is busy writing on another Volume.\n"), dev->print_name());
640       Dmsg1(100, "%s", jcr->errmsg);
641       goto bail_out;
642    }
643
644    dev->reserved_device++;
645    Dmsg1(200, "Inc reserve=%d\n", dev->reserved_device);
646    dcr->reserved_device = true;
647    ok = true;
648
649 bail_out:
650    dev->unblock();
651    return ok;
652 }
653
654 /*
655  * Returns: 1 if drive can be reserved
656  *          0 if we should wait
657  *         -1 on error
658  */
659 static int can_reserve_drive(DCR *dcr, bool PreferMountedVols) 
660 {
661    DEVICE *dev = dcr->dev;
662    JCR *jcr = dcr->jcr;
663
664    if (PreferMountedVols && !dev->VolHdr.VolumeName[0] && dev->is_tape()) {
665       return 0;                 /* No volume mounted */
666    }
667
668    /*
669     * Handle the case that there are no writers
670     */
671    if (dev->num_writers == 0) {
672       /* Now check if there are any reservations on the drive */
673       if (dev->reserved_device) {           
674          /* Yes, now check if we want the same Pool and pool type */
675          if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
676              strcmp(dev->pool_type, dcr->pool_type) == 0) {
677             /* OK, compatible device */
678          } else {
679             /* Drive not suitable for us */
680             return 0;                 /* wait */
681          }
682       } else if (dev->can_append()) {
683          /* Device in append mode, check if changing pool */
684          if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
685              strcmp(dev->pool_type, dcr->pool_type) == 0) {
686             /* OK, compatible device */
687          } else {
688             /* Changing pool, unload old tape if any in drive */
689             unload_autochanger(dcr, 0);
690          }
691       }
692       /* Device is available but not yet reserved, reserve it for us */
693       bstrncpy(dev->pool_name, dcr->pool_name, sizeof(dev->pool_name));
694       bstrncpy(dev->pool_type, dcr->pool_type, sizeof(dev->pool_type));
695       return 1;                       /* reserve drive */
696    }
697
698    /*
699     * Check if the device is in append mode with writers (i.e.
700     *  available if pool is the same).
701     */
702    if (dev->can_append() || dev->num_writers > 0) {
703       Dmsg0(190, "device already in append.\n");
704       /* Yes, now check if we want the same Pool and pool type */
705       if (strcmp(dev->pool_name, dcr->pool_name) == 0 &&
706           strcmp(dev->pool_type, dcr->pool_type) == 0) {
707          /* OK, compatible device */
708          return 1;
709       } else {
710          /* Drive not suitable for us */
711          Jmsg(jcr, M_WARNING, 0, _("Wanted Pool \"%s\", but device %s is using Pool \"%s\" .\n"), 
712                  dcr->pool_name, dev->print_name(), dev->pool_name);
713          return 0;                    /* wait */
714       }
715    } else {
716       Pmsg0(000, _("Logic error!!!! Should not get here.\n"));
717       Jmsg0(jcr, M_FATAL, 0, _("Logic error!!!! Should not get here.\n"));
718       return -1;                      /* error, should not get here */
719    }
720
721    return 0;
722 }