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