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