]> git.sur5r.net Git - bacula/bacula/blob - bacula/patches/testing/faketape2.patch
ebl update
[bacula/bacula] / bacula / patches / testing / faketape2.patch
1 Index: src/stored/faketape.c
2 ===================================================================
3 --- src/stored/faketape.c       (révision 7100)
4 +++ src/stored/faketape.c       (copie de travail)
5 @@ -170,6 +170,7 @@
6  int faketape::tape_op(struct mtop *mt_com)
7  {
8     int result=0;
9 +   int count = mt_com->mt_count;
10  
11     if (!online) {
12        errno = ENOMEDIUM;
13 @@ -193,11 +194,15 @@
14        break;
15  
16     case MTFSF:                  /* Forward space over mt_count filemarks. */
17 -      result = fsf(mt_com->mt_count);
18 +      do {
19 +        result = fsf();
20 +      } while (--count > 0 && result == 0);
21        break;
22  
23     case MTBSF:                  /* Backward space over mt_count filemarks. */
24 -      result = bsf(mt_com->mt_count);
25 +      do {
26 +        result = bsf();
27 +      } while (--count > 0 && result == 0);
28        break;
29  
30     case MTFSR:      /* Forward space over mt_count records (tape blocks). */
31 @@ -222,16 +227,20 @@
32        break;
33  
34     case MTWEOF:                 /* Write mt_count filemarks. */
35 -      result = weof(mt_com->mt_count);
36 +      do {
37 +        result = weof();
38 +      } while (result == 0 && --count > 0);
39        break;
40  
41     case MTREW:                  /* Rewind. */
42        Dmsg0(dbglevel, "rewind faketape\n");
43 +      check_eof();
44        atEOF = atEOD = false;
45        atBOT = true;
46        current_file = 0;
47        current_block = 0;
48 -      seek_file();
49 +      lseek(fd, 0, SEEK_SET);
50 +      read_next_fm(true);
51        break;
52  
53     case MTOFFL:                 /* put tape offline */
54 @@ -253,19 +262,30 @@
55        break;
56  
57     case MTEOM:/* Go to the end of the recorded media (for appending files). */
58 +      while (next_FM) {
59 +        lseek(fd, next_FM, SEEK_SET);
60 +        if (read_next_fm(true)) {
61 +           current_file++;
62 +        }
63 +      }
64 +      off_t l;
65 +      while (::read(fd, &l, sizeof(l)) > 0) {
66 +        if (l) {
67 +           lseek(fd, l, SEEK_CUR);
68 +        } else {
69 +           ASSERT(0);
70 +        }
71 +        Dmsg0(dbglevel, "skip 1 block\n");
72 +      }
73 +      current_block = -1;
74 +      atEOF = false;
75 +      atEOD = true;
76 +
77  /*
78     file number = 3
79     block number = -1
80  */
81        /* Can be at EOM */
82 -      atBOT = false;
83 -      atEOF = false;
84 -      atEOD = true;
85 -      atEOT = false;
86 -
87 -      current_file = last_file;
88 -      current_block = -1;
89 -      seek_file();
90        break;
91  
92     case MTERASE:                /* not used by bacula */
93 @@ -275,7 +295,8 @@
94  
95        current_file = 0;
96        current_block = -1;
97 -      seek_file();
98 +      lseek(fd, 0, SEEK_SET);
99 +      read_next_fm(true);
100        truncate_file();
101        break;
102  
103 @@ -405,8 +426,8 @@
104     atEOT = false;
105     atEOD = false;
106     online = false;
107 -   inplace = false;
108     needEOF = false;
109 +   eot_count = 0;
110  
111     file_block = 0;
112     last_file = 0;
113 @@ -436,7 +457,8 @@
114     ASSERT(buffer);
115  
116     unsigned int nb;
117 -   Dmsg3(dbglevel, "write len=%i %i:%i\n", count, current_file,current_block);
118 +   Dmsg3(dbglevel+1, "write len=%i %i:%i\n", 
119 +        count, current_file,current_block);
120  
121     if (atEOT) {
122        Dmsg0(dbglevel, "write nothing, EOT !\n");
123 @@ -444,8 +466,6 @@
124        return -1;
125     }
126  
127 -   check_inplace();
128 -
129     if (!atEOD) {                /* if not at the end of the data */
130        truncate_file();
131     }
132 @@ -460,14 +480,6 @@
133  
134     needEOF = true;              /* next operation need EOF mark */
135  
136 -//   if ((count + file_size) > max_size) {
137 -//      Dmsg2(dbglevel, 
138 -//          "EOT writing only %i of %i requested\n", 
139 -//          max_size - file_size, count);
140 -//      count = max_size - file_size;
141 -//      atEOT = true;
142 -//   }
143 -
144     uint32_t size = count;
145     ::write(fd, &size, sizeof(uint32_t));
146     nb = ::write(fd, buffer, count);
147 @@ -484,43 +496,66 @@
148     return nb;
149  }
150  
151 -int faketape::weof(int count)
152 +/*
153 + *  +---+---------+---+------------------+---+-------------------+
154 + *  |00N|  DATA   |0LN|   DATA           |0LC|     DATA          |
155 + *  +---+---------+---+------------------+---+-------------------+
156 + *
157 + *  0 : zero
158 + *  L : Last FileMark offset
159 + *  N : Next FileMark offset
160 + *  C : Current FileMark Offset
161 + */
162 +int faketape::weof()
163  {
164     ASSERT(online);
165     ASSERT(current_file >= 0);
166 -   Dmsg3(dbglevel, "Writing EOF %i:%i last=%i\n", 
167 -         current_file, current_block,last_file);
168 +
169     if (atEOT) {
170        errno = ENOSPC;
171        current_block = -1;
172        return -1;
173     }
174 -   needEOF = false;
175  
176 -   check_inplace();
177 -   truncate_file();             /* nothing after this point */
178 +   if (!atEOD) {
179 +      truncate_file();             /* nothing after this point */
180 +   }
181  
182 +   last_FM = cur_FM;
183 +   cur_FM = lseek(fd, 0, SEEK_CUR); // current position
184 +   
185 +   /* update previous next_FM  */
186 +   lseek(fd, last_FM + sizeof(uint32_t)+sizeof(off_t), SEEK_SET);
187 +   ::write(fd, &cur_FM, sizeof(off_t));
188 +   lseek(fd, cur_FM, SEEK_SET);
189 +
190 +   next_FM = 0;
191 +
192     uint32_t c=0;
193 -   ::write(fd, &c, sizeof(uint32_t));
194 +   ::write(fd, &c,       sizeof(uint32_t)); // EOF
195 +   ::write(fd, &last_FM, sizeof(last_FM));  // F-1
196 +   ::write(fd, &next_FM, sizeof(next_FM));  // F   (will be updated next time)
197  
198 -   current_file += count;
199 +   current_file++;
200     current_block = 0;
201 -   seek_file();
202  
203 -   c=0;
204 -   ::write(fd, &c, sizeof(uint32_t));   
205 -   lseek(fd, lseek(fd, 0, SEEK_CUR) - sizeof(uint32_t), SEEK_SET);
206 -
207 +   needEOF = false;
208     atEOD = false;
209     atBOT = false;
210     atEOF = true;
211  
212 -   update_pos();
213 +   last_file = MAX(current_file, last_file);
214  
215 +   Dmsg4(dbglevel, "Writing EOF %i:%i last=%lli cur=%lli next=0\n", 
216 +         current_file, current_block, last_FM, cur_FM);
217 +
218     return 0;
219  }
220  
221 -int faketape::fsf(int count)
222 +/*
223 + * Go to next FM
224 + */
225 +int faketape::fsf()
226  {   
227     ASSERT(online);
228     ASSERT(current_file >= 0);
229 @@ -528,24 +563,33 @@
230  /*
231   * 1 0 -> fsf -> 2 0 -> fsf -> 2 -1
232   */
233 -   check_inplace();
234 -   check_eof();
235  
236 -   int ret;
237 +   int ret=0;
238     if (atEOT || atEOD) {
239        errno = EIO;
240        current_block = -1;
241        return -1;
242     }
243  
244 -   atBOT = atEOF = false;
245 -   Dmsg3(dbglevel+1, "fsf %i+%i <= %i\n", current_file, count, last_file);
246 +   atBOT = false;
247 +   Dmsg2(dbglevel+1, "fsf %i <= %i\n", current_file, last_file);
248  
249 -   if ((current_file + count) <= last_file) {
250 -      current_file += count;
251 -      current_block = 0;
252 +   if (next_FM > cur_FM) {     /* not the last file */
253 +      lseek(fd, next_FM, SEEK_SET);
254 +      read_next_fm(true);
255 +      current_file++;
256 +      atEOF = true;
257        ret = 0;
258 -   } else {
259 +
260 +   } else if (atEOF) {         /* last file mark */
261 +      current_block=-1;
262 +      errno = EIO;
263 +      atEOF = false;
264 +      atEOD = true;
265 +
266 +   } else {                    /* last file, but no at the end */
267 +      fsr(100000);
268 +
269        Dmsg0(dbglevel, "Try to FSF after EOT\n");
270        errno = EIO;
271        current_file = last_file ;
272 @@ -553,10 +597,47 @@
273        atEOD=true;
274        ret = -1;
275     }
276 -   seek_file();
277     return ret;
278  }
279  
280 +/* /------------\ /---------------\
281 + * +---+------+---+---------------+-+
282 + * |OLN|      |0LN|               | |
283 + * +---+------+---+---------------+-+
284 + */
285 +bool faketape::read_next_fm(bool read_all /* read the 0 byte */)
286 +{
287 +   return read_fm(read_all);
288 +}
289 +
290 +bool faketape::read_fm(bool read_all /* read the 0 byte */)
291 +{
292 +   int ret;
293 +   uint32_t c;
294 +   if (read_all) {
295 +      ::read(fd, &c, sizeof(c));
296 +      if (c != 0) {
297 +        lseek(fd, cur_FM, SEEK_SET);
298 +        return false;
299 +      }
300 +   }
301 +
302 +   cur_FM = lseek(fd, 0, SEEK_CUR) - sizeof(c);
303 +
304 +   ::read(fd, &last_FM, sizeof(last_FM));
305 +   ret = ::read(fd, &next_FM, sizeof(next_FM));
306 +
307 +   current_block=0;
308 +   
309 +   Dmsg3(dbglevel, "Read FM cur=%lli last=%lli next=%lli\n", 
310 +        cur_FM, last_FM, next_FM);
311 +
312 +   return (ret == sizeof(next_FM));
313 +}
314 +
315 +/*
316 + * TODO: Check fsr with EOF
317 + */
318  int faketape::fsr(int count)
319  {
320     ASSERT(online);
321 @@ -566,9 +647,9 @@
322     int i,nb, ret=0;
323     off_t where=0;
324     uint32_t s;
325 -   Dmsg3(dbglevel, "fsr %i:%i count=%i\n", current_file,current_block, count);
326 +   Dmsg4(dbglevel, "fsr %i:%i EOF=%i c=%i\n", 
327 +        current_file,current_block,atEOF,count);
328  
329 -   check_inplace();
330     check_eof();
331  
332     if (atEOT) {
333 @@ -595,31 +676,29 @@
334                 current_file, current_block, nb,s);
335           errno = EIO;
336           ret = -1;
337 -         if (current_file < last_file) {
338 -            current_block = 0;
339 +        if (next_FM) {
340              current_file++;
341 -            seek_file();
342 -         }
343 +           read_next_fm(false);
344 +        }
345           atEOF = true;          /* stop the loop */
346        }
347     }
348  
349 -   find_maxfile();              /* refresh stats */
350 -
351     return ret;
352  }
353  
354 +/*
355 + * BSR + EOF => begin of EOF + EIO
356 + * BSR + BSR + EOF => last block
357 + * current_block = -1
358 + */
359  int faketape::bsr(int count)
360  {
361 -   Dmsg2(dbglevel, "bsr current_block=%i count=%i\n", 
362 -         current_block, count);
363 -
364     ASSERT(online);
365     ASSERT(current_file >= 0);
366     ASSERT(count == 1);
367     ASSERT(fd >= 0);
368  
369 -   check_inplace();
370     check_eof();
371  
372     if (!count) {
373 @@ -635,29 +714,39 @@
374     int orig_f = current_file;
375     int orig_b = current_block;
376  
377 +   Dmsg4(dbglevel, "bsr cur_blk=%i count=%i cur=%lli cur_FM=%lli\n", 
378 +         current_block, count, orig, cur_FM);
379 +
380     /* begin of tape, do nothing */
381     if (atBOT) {
382        errno = EIO;
383        return -1;
384     }
385  
386 +   /* at EOF 0:-1 BOT=0 EOD=0 EOF=0 ERR: Input/output error  */
387     if (atEOF) {
388 -      if (!current_block) {
389 -        if (current_file > 0) {
390 -           current_file--;
391 -        }
392 -        current_block=-1;
393 -        errno = EIO;
394 -        return -1;
395 -
396 -      } else {
397 -        atEOF=false;
398 +      lseek(fd, cur_FM, SEEK_SET);
399 +      atEOF = false;
400 +      if (current_file > 0) {
401 +        current_file--;
402        }
403 +      current_block=-1;
404 +      errno = EIO;
405 +      return -1;
406     }
407  
408 -   current_block=0;
409 -   seek_file();
410 +   /*
411 +    * First, go to cur/last_FM and read all blocks to find the good one
412 +    */
413 +   if (cur_FM == orig) {       /* already just before  EOF */
414 +      lseek(fd, last_FM, SEEK_SET);
415  
416 +   } else {
417 +      lseek(fd, cur_FM, SEEK_SET);
418 +   }
419 +
420 +   ret = read_fm(true);
421 +
422     do {
423        if (!atEOF) {
424           last2 = last;
425 @@ -674,14 +763,14 @@
426        lseek(fd, last2, SEEK_SET);
427        current_file = last_f;
428        current_block = last_b - 1;
429 -      Dmsg3(dbglevel, "set offset2=%lli %i:%i\n", 
430 +      Dmsg3(dbglevel, "1 set offset2=%lli %i:%i\n", 
431              last, current_file, current_block);
432  
433     } else if (last > 0) {
434        lseek(fd, last, SEEK_SET);
435        current_file = last_f;
436        current_block = last_b;
437 -      Dmsg3(dbglevel, "set offset=%lli %i:%i\n", 
438 +      Dmsg3(dbglevel, "2 set offset=%lli %i:%i\n", 
439              last, current_file, current_block);
440     } else {
441        lseek(fd, orig, SEEK_SET);
442 @@ -693,38 +782,45 @@
443     Dmsg2(dbglevel, "bsr %i:%i\n", current_file, current_block);
444     errno=0;
445     atEOT = atEOF = atEOD = false;
446 -   atBOT = (current_block == 0 && current_file == 0);
447 +   atBOT = (lseek(fd, 0, SEEK_CUR) - (sizeof(uint32_t)+2*sizeof(off_t))) == 0;
448  
449 -   current_block = -1;
450 +   if (orig_b == -1) {
451 +      current_block = orig_b;
452 +   }
453  
454     return 0;
455  }
456  
457 -int faketape::bsf(int count)
458 +/* BSF => just before last EOF
459 + * EOF + BSF => just before EOF
460 + * file 0 + BSF => BOT + errno
461 + */
462 +int faketape::bsf()
463  {
464     ASSERT(online);
465     ASSERT(current_file >= 0);
466 -   Dmsg3(dbglevel, "bsf %i:%i count=%i\n", current_file, current_block, count);
467 +   Dmsg2(dbglevel, "bsf %i:%i count=%i\n", current_file, current_block);
468     int ret = 0;
469  
470 -   check_inplace();
471     check_eof();
472  
473     atBOT = atEOF = atEOT = atEOD = false;
474  
475 -   if (current_file - count < 0) {
476 +   if (current_file == 0) {/* BOT + errno */      
477 +      lseek(fd, 0, SEEK_SET);
478 +      read_fm(true);
479        current_file = 0;
480        current_block = 0;
481        atBOT = true;
482        errno = EIO;
483        ret = -1;
484     } else {
485 -      current_file = current_file - count + 1;
486 -      current_block = -1;
487 -      seek_file();
488 +      Dmsg1(dbglevel, "bfs last=%lli\n", last_FM);
489 +      lseek(fd, last_FM, SEEK_SET);
490 +      read_fm(true);           /* update last/cur/next_FM */
491 +      lseek(fd, cur_FM, SEEK_SET);
492        current_file--;
493 -      /* go just before last EOF */
494 -      lseek(fd, lseek(fd, 0, SEEK_CUR) - sizeof(uint32_t), SEEK_SET);
495 +      current_block=-1;
496     }
497     return ret;
498  }
499 @@ -749,6 +845,9 @@
500     return 0;
501  }
502  
503 +/* A filemark is automatically written to tape if the last tape operation
504 + * before close was a write.
505 + */
506  int faketape::close()
507  {
508     check_eof();
509 @@ -756,18 +855,15 @@
510     fd = -1;
511     return 0;
512  }
513 +
514  /*
515 - **rb
516 - **status
517 - * EOF Bacula status: file=2 block=0
518 - * Device status: EOF ONLINE IM_REP_EN file=2 block=0
519 - **rb
520 - **status
521 - * EOD EOF Bacula status: file=2 block=0
522 - * Device status: EOD ONLINE IM_REP_EN file=2 block=-1
523 - *
524 + * When a filemark is encountered while reading, the following happens.  If
525 + * there are data remaining in the buffer when the filemark is found, the
526 + * buffered data is returned.  The next read returns zero bytes.  The following
527 + * read returns data from the next file.  The end of recorded data is sig‐
528 + * naled by returning zero bytes for two consecutive read calls.  The third
529 + * read returns an error.
530   */
531 -
532  int faketape::read(void *buffer, unsigned int count)
533  {
534     ASSERT(online);
535 @@ -775,7 +871,7 @@
536     unsigned int nb;
537     uint32_t s;
538     
539 -   Dmsg2(dbglevel, "read %i:%i\n", current_file, current_block);
540 +   Dmsg2(dbglevel+1, "read %i:%i\n", current_file, current_block);
541  
542     if (atEOT || atEOD) {
543        errno = EIO;
544 @@ -783,7 +879,7 @@
545     }
546  
547     if (atEOF) {
548 -      if (current_file >= last_file) {
549 +      if (!next_FM) {
550           atEOD = true;
551           atEOF = false;
552           current_block=-1;
553 @@ -792,7 +888,6 @@
554        atEOF=false;
555     }
556  
557 -   check_inplace();
558     check_eof();
559  
560     atEOD = atBOT = false;
561 @@ -813,11 +908,10 @@
562  
563     if (!s) {                    /* EOF */
564        atEOF = true;
565 -      if (current_file < last_file) { /* move to next file if possible */
566 -         current_file++;
567 -         current_block = 0;
568 -         inplace=false;
569 +      if (read_next_fm(false)) {
570 +        current_file++;
571        }
572 +
573        return 0;
574     }
575  
576 @@ -825,7 +919,7 @@
577     nb = ::read(fd, buffer, s);
578     if (s != nb) {              /* read error */
579        errno=EIO;
580 -      atEOT = true;
581 +      set_eot();
582        current_block = -1;
583        Dmsg0(dbglevel, "EOT during reading\n");
584        return -1;
585 @@ -860,36 +954,24 @@
586        return -1;
587     }
588  
589 -   /* open volume descriptor and get this->fd */
590 -   find_maxfile();
591 -
592     file_block = 0;
593     current_block = 0;
594     current_file = 0;
595 +   cur_FM = next_FM = last_FM = 0;
596     needEOF = false;
597 -   inplace = true;
598     atBOT = true;
599     atEOT = atEOD = false;
600  
601 -   return fd;
602 -}
603 -
604 -/*
605 - * read volume to get the last file number
606 - */
607 -int faketape::find_maxfile()
608 -{
609 -   struct stat statp;
610 -   if (fstat(fd, &statp) != 0) {
611 -      return 0;
612 +   
613 +   if (!read_fm(true)) {
614 +      weof();
615 +      last_file = current_file=0;
616     }
617 -   last_file = statp.st_size>>FILE_OFFSET;
618 -      
619 -   Dmsg1(dbglevel+1, "last_file=%i\n", last_file);
620  
621 -   return last_file;
622 +   return fd;
623  }
624  
625 +/* use this to track file usage */
626  void faketape::update_pos()
627  {
628     ASSERT(online);
629 @@ -901,32 +983,12 @@
630     Dmsg1(dbglevel+1, "update_pos=%i\n", file_block);
631  
632     if (file_block > max_block) {
633 -      atEOT = true;
634 +      set_eot();
635     } else {
636        atEOT = false;
637     }
638  }
639  
640 -int faketape::seek_file()
641 -{
642 -   ASSERT(online);
643 -   ASSERT(current_file >= 0);
644 -   Dmsg2(dbglevel, "seek_file %i:%i\n", current_file, current_block);
645 -   inplace = true;
646 -
647 -   off_t pos = ((off_t)current_file)<<FILE_OFFSET;
648 -   if(lseek(fd, pos, SEEK_SET) == -1) {
649 -      return -1;
650 -   }
651 -
652 -   last_file = MAX(last_file, current_file);
653 -   if (current_block > 0) {
654 -      fsr(current_block);
655 -   }
656 -
657 -   return 0;
658 -}
659 -
660  void faketape::dump()
661  {
662     Dmsg0(dbglevel+1, "===================\n");
663 Index: src/stored/faketape.h
664 ===================================================================
665 --- src/stored/faketape.h       (révision 7100)
666 +++ src/stored/faketape.h       (copie de travail)
667 @@ -56,35 +56,39 @@
668  private:
669     int         fd;              /* Our file descriptor */
670  
671 -   off_t       file_block;       /* size */
672 +   off_t       file_block;     /* size */
673     off_t       max_block;
674  
675 +   off_t       last_FM;                /* last file mark (last file) */
676 +   off_t       next_FM;                /* next file mark (next file) */
677 +   off_t       cur_FM;         /* current file mark */
678 +
679     bool        atEOF;           /* End of file */
680     bool        atEOT;           /* End of media */
681     bool        atEOD;           /* End of data */
682     bool        atBOT;           /* Begin of tape */
683     bool        online;          /* volume online */
684 -   bool        inplace;         /* have to seek before writing ? */
685     bool        needEOF;         /* check if last operation need eof */
686  
687     int32_t     last_file;       /* last file of the volume */
688     int32_t     current_file;    /* current position */
689     int32_t     current_block;   /* current position */
690 +   int         eot_count;      /* count eot reads */
691  
692     void destroy();
693 -   int find_maxfile();
694     int offline();
695     int truncate_file();
696 -   int seek_file();
697 -   void check_eof() { if(needEOF) weof(1);};
698 -   void check_inplace() { if (!inplace) seek_file();};
699 +   void check_eof() { if(needEOF) weof();};
700     void update_pos();
701 +   bool read_fm(bool readfirst);
702 +   bool read_next_fm(bool readfirst);
703 +   void set_eot() { eot_count=0; atEOT=true;};
704  
705  public:
706 -   int fsf(int count);
707 +   int fsf();
708     int fsr(int count);
709 -   int weof(int count);
710 -   int bsf(int count);
711 +   int weof();
712 +   int bsf();
713     int bsr(int count);
714  
715     faketape();