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