]> git.sur5r.net Git - bacula/bacula/commitdiff
ebl update
authorEric Bollengier <eric@eb.homelinux.org>
Sun, 4 May 2008 14:08:20 +0000 (14:08 +0000)
committerEric Bollengier <eric@eb.homelinux.org>
Sun, 4 May 2008 14:08:20 +0000 (14:08 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@6889 91ce42f0-d328-0410-95d8-f526ca767f89

bacula/patches/testing/faketape.c
bacula/patches/testing/faketape.h

index c9196d9282f23c6d09be2954682bbb531c06339a..b8fc8efa2f5e7ffa4451882649005393eccd9192 100644 (file)
@@ -67,6 +67,8 @@ static bool put_tape(faketape *ftape)
 
 int faketape_open(const char *pathname, int flags, int mode)
 {
+   ASSERT(pathname != NULL);
+
    int fd;
    faketape *tape = new faketape();
    fd = tape->open(pathname, flags, mode);
@@ -139,7 +141,6 @@ int faketape_ioctl(int fd, unsigned long int request, ...)
 int faketape::tape_op(struct mtop *mt_com)
 {
    int result=0;
-   struct stat statp;
    
    switch (mt_com->mt_op)
    {
@@ -158,23 +159,10 @@ int faketape::tape_op(struct mtop *mt_com)
       break;
 
    case MTFSF:                 /* Forward space over mt_count filemarks. */
-      /* we are already at EOT */
-      if (current_file > max_file) {
-        atEOF = true;
-        errno = EIO;
-        result = -1;
-      }
-
-      /* we are at the last file */
-      if (current_file == max_file) {
-        current_file++;
-        atEOF = true;
-      }
-
       break;
 
    case MTBSF:                 /* Backward space over mt_count filemarks. */
-      current_file = current_file - mt_op->mt_count;
+      current_file = current_file - mt_com->mt_count;
       if (current_file < 0) {
         current_file = 0;
         errno = EIO;
@@ -182,7 +170,7 @@ int faketape::tape_op(struct mtop *mt_com)
       }
       atEOD = false;
       atEOF = false;
-      atEOM = false;
+      atBOT = false;
       open_file();
       break;
 
@@ -200,39 +188,27 @@ int faketape::tape_op(struct mtop *mt_com)
     block number = 0
 */
       /* tester si on se trouve a la fin du fichier */
-      fseek(cur_fd, SEEK_CUR, tape_info.block_size*mt_op->mt_count);
+      lseek(cur_fd, SEEK_CUR, tape_info.block_size*mt_com->mt_count);
       break;
 
    case MTBSR:      /* Backward space over mt_count records (tape blocks). */
-
-/*
-   file number = 1
-   block number = -1
-
-   mt: /dev/lto2: Erreur d'entrée/sortie
-
-   file number = 0
-   block number = -1
-*/
-
-      fstat(cur_file, &statp);
-      off_t cur_pos = lseek(cur_fd, 0, SEEK_CUR);
-
-      fseek(cur_fd, SEEK_CUR, tape_info.block_size*mt_op->mt_count);
+      result = -1;
       break;
 
    case MTWEOF:                        /* Write mt_count filemarks. */
+      weof(mt_com->mt_count);
       break;
 
    case MTREW:                 /* Rewind. */
-      atEOF = atEOD = atEOM = false;
+      close_file();
+      atEOF = atEOD = false;
+      atBOT = true;
       current_file = 0;
-      open_file();
+      current_block = 0;
       break;
 
    case MTOFFL:                        /* put tape offline */
-      // check if can_read/can_write
-      result = 0;
+      result = offline();
       break;
 
    case MTRETEN:               /* Re-tension tape. */
@@ -361,16 +337,21 @@ int faketape::delete_files(int startfile)
    struct dirent *dir;
    struct stat statp;
 
+   Dmsg1(dbglevel, "delete_files %i\n", startfile);
+
    fp_dir = opendir(this->volume);
    if (!fp_dir) {
-      this->max_file=0;
+      this->last_file=0;
       this->size = 0;
       return -1;
    }
 
    this->size = 0;
 
-   /* search for all digit file */
+   /* search for all digit files 
+    * and we remove all ones that are greater than
+    * startfile
+    */
    while ((dir = readdir (fp_dir)) != NULL)
    {
       Mmsg(tmp, "%s/%s", this->volume, dir->d_name);
@@ -379,11 +360,11 @@ int faketape::delete_files(int startfile)
       for(p = dir->d_name; *p && isdigit(*p); p++)
       {
         cur *= 10;
-        cur += *p;
+        cur += *p - '0';
       }
-      if (!*p && cur) {
+      if (!*p && cur > 0) {
         if (cur >= startfile) { /* remove it */
-           unlink(tmp);
+           unlink(tmp.c_str());
         } else {
            if (lstat(tmp.c_str(), &statp) == 0) {
               this->size += statp.st_size;
@@ -394,18 +375,26 @@ int faketape::delete_files(int startfile)
    }
 
    closedir(fp_dir);
-   this->max_file = max;
+   this->last_file = max;
    return max;
 }
 
 faketape::faketape()
 {
-   fd = 0;
-   atEOF = 0;
-   atEOM = 0;
+   fd = -1;
+   cur_fd = -1;
+
+   atEOF = false;
+   atBOT = false;
+   atEOT = false;
+   atEOD = false;
+   online = false;
+   
+   size = 0;
+   last_file = 0;
    current_file = 0;
-   current_block = 0;
-   max_file = 0;
+   current_block = -1;
+   max_size = 10000000;
 
    volume = get_pool_memory(PM_NAME);
    cur_file = get_pool_memory(PM_NAME);
@@ -426,30 +415,188 @@ int faketape::get_fd()
 
 int faketape::write(const void *buffer, unsigned int count)
 {
-   ASSERT(cur_fd > 0);
-   if (current_block == -1) {
+   unsigned int nb;
+   check_file();
+
+   if (atEOT) {
+      return 0;
+   }
+
+   current_block++;
+
+   atBOT = false;
+
+   /* TODO: remove all files > current_file and 
+    * remove blocks > current_block 
+    */
+   if (count + size > max_size) {
+      Dmsg2(dbglevel, 
+           "EOT writing only %i of %i requested\n", 
+           max_size - size, count);
+      count = max_size - size;
+      atEOT = true;
+   }
+
+   nb = ::write(cur_fd, buffer, count);
+   
+   if (nb != count) {
+      atEOT = true;
+      Dmsg2(dbglevel, 
+           "Not enough space writing only %i of %i requested\n", 
+           nb, count);
+   }
+
+   return nb;
+}
+
+int faketape::weof(int count)
+{
+   if (atEOT) {
+      current_block = -1;
+      return -1;
+   }
+
+   count--;                    /* end this file */
+   ftruncate(cur_fd, lseek(cur_fd, 0, SEEK_CUR));
+   close_file();
+   current_file++;
+
+   /* we erase all previous information */
+   if (last_file > current_file) {
+      delete_files(current_file);
+   }
+
+   for (; count>0 ; count--) {
+      current_file++;
       open_file();
    }
-   /* remove all file > current_file */
-   return ::write(cur_fd, buffer, count);
+   current_block=0;
+   atEOF = true;
+   atEOD = false;
+   return 0;
 }
 
-int faketape::close()
+int faketape::fsf(int count)
+{
+
+/*
+ * 1 0 -> fsf -> 2 0 -> fsf -> 2 -1
+ */
+
+   if (atEOT) {
+      current_block = -1;
+      return -1;
+   }
+
+   close_file();
+
+   if (current_file + count <= last_file) {
+      current_file += count;
+      current_block = 0;
+      return 0;
+   } else {
+      current_file = last_file;
+      current_block = -1;
+      atEOT=true;
+      return -1;
+   }
+}
+
+int faketape::bsf(int count)
+{
+
+/*
+ * 1 0 -> fsf -> 2 0 -> fsf -> 2 -1
+ */
+   close_file();
+   atEOT = atEOD = false;
+
+   if (current_file - count < 0) {
+      current_file = 0;
+      current_block = 0;
+      atBOT = true;
+      return -1;
+   }
+
+   current_file = current_file - count;
+   current_block = 0;
+   if (!current_file) {
+      atBOT = true;
+   }
+
+   return 1;
+}
+
+/* 
+ * Put faketape in offline mode
+ */
+int faketape::offline()
 {
    ASSERT(cur_fd > 0);
-   ::close(cur_fd);
+
+   close_file();
+
+   cur_fd = -1;
+   atEOF = false;
+   atEOT = false;
+   atEOD = false;
+   atBOT = false;
+
+   current_file = -1;
+   current_block = -1;
+   last_file = 0;
+   return 0;
+}
+
+int faketape::close_file()
+{
+   if (cur_fd > 0) {
+      ::close(cur_fd);
+      cur_fd = -1;
+   }
+   return 0;
+}
+
+int faketape::close()
+{
+   close_file();
    ::close(fd);
 
    return 0;
 }
+/*
+ **rb
+ **status
+ * EOF Bacula status: file=2 block=0
+ * Device status: EOF ONLINE IM_REP_EN file=2 block=0
+ **rb
+ **status
+ * EOD EOF Bacula status: file=2 block=0
+ * Device status: EOD ONLINE IM_REP_EN file=2 block=-1
+ *
+ */
 
 int faketape::read(void *buffer, unsigned int count)
 {
-   ASSERT(cur_fd > 0);
-   if (current_block == -1) {
-      open_file();
+   unsigned int nb;
+   check_file();
+
+   if (atEOT || atEOD) {
+      return 0;
    }
-   return ::read(cur_fd, buffer, count);
+
+   atBOT = false;
+
+   nb = ::read(cur_fd, buffer, count);
+   if (count != nb) {
+      atEOF = true;
+      if (current_file == last_file) {
+        atEOD = true;
+        current_block = -1;
+      }
+      Dmsg0(dbglevel, "EOF during reading\n");
+   }
+   return nb;
 }
 
 int faketape::read_volinfo()
@@ -457,7 +604,7 @@ int faketape::read_volinfo()
    struct stat statp;
    memset(&tape_info, 0, sizeof(FTAPE_FORMAT));
 
-   Dmsg2(0, "Info %p %p\n", cur_info, volume);
+   Dmsg2(0, "read_volinfo %p %p\n", cur_info, volume);
    Mmsg(cur_info, "%s/info", volume);
    fd = ::open(cur_info, O_CREAT | O_RDWR | O_BINARY, 0640);
    
@@ -465,7 +612,7 @@ int faketape::read_volinfo()
       return -1;
    }
    
-   fstat(cur_info, &statp);
+   fstat(fd, &statp);
    
    /* read volume info */
    int nb = ::read(fd, &tape_info, sizeof(FTAPE_FORMAT));
@@ -530,7 +677,7 @@ int faketape::find_maxfile()
 
    fp_dir = opendir(this->volume);
    if (!fp_dir) {
-      max_file=0;
+      last_file=0;
       return -1;
    }
 
@@ -558,13 +705,14 @@ int faketape::find_maxfile()
    }
 
    closedir(fp_dir);
-   this->max_file = max;
+   this->last_file = max;
    return max;
 }
 
 int faketape::open_file() 
 {
-   if (cur_fd) {
+   ASSERT(current_file >= 0);
+   if (cur_fd > 0) {
       ::close(cur_fd);
    }
 
@@ -574,7 +722,9 @@ int faketape::open_file()
       return -1;
    }
    current_block = 0;
-   max_file = (max_file > current_file)?max_file:current_file;
+   last_file = (last_file > current_file)?last_file:current_file;
+
+   Dmsg1(dbglevel, "open_file %s %i\n", cur_file);
 
    return cur_fd;
 
@@ -582,14 +732,105 @@ int faketape::open_file()
 
 void faketape::dump()
 {
-   Dmsg1(dbglevel, "max_file=%i\n", max_file);
+   Dmsg0(dbglevel, "===================\n");
+   Dmsg1(dbglevel, "last_file=%i\n", last_file);
    Dmsg1(dbglevel, "current_file=%i\n", current_file);
    Dmsg1(dbglevel, "volume=%s\n", volume);
-   Dmsg1(dbglevel, "cur_info=%s\n", cur_info);
    Dmsg1(dbglevel, "cur_file=%s\n", cur_file);  
    Dmsg1(dbglevel, "size=%i\n", size);  
+   Dmsg1(dbglevel, "EOF=%i\n", atEOF);  
+   Dmsg1(dbglevel, "EOT=%i\n", atEOT);  
+   Dmsg1(dbglevel, "EOD=%i\n", atEOD);  
 }
 
+/****************************************************************
+
+#define GMT_EOF(x)              ((x) & 0x80000000)
+#define GMT_BOT(x)              ((x) & 0x40000000)
+#define GMT_EOT(x)              ((x) & 0x20000000)
+#define GMT_SM(x)               ((x) & 0x10000000)
+#define GMT_EOD(x)              ((x) & 0x08000000)
+
+
+ GMT_EOF(x) : La bande est positionnée juste après une filemark (toujours faux
+     après une opération MTSEEK).
+
+ GMT_BOT(x) : La bande est positionnée juste au début du premier fichier
+     (toujours faux après une opération MTSEEK).
+ GMT_EOT(x) : Une opération a atteint la fin physique de la bande (End Of
+ Tape).
+
+ GMT_SM(x) : La bande est positionnée sur une setmark (toujours faux après une
+ opération MTSEEK).
+
+ GMT_EOD(x) : La bande est positionnée à la fin des données enregistrées.
+
+
+blkno = -1 (after MTBSF MTBSS or MTSEEK)
+fileno = -1 (after MTBSS or MTSEEK)
+
+*** mtx load
+drive type = Generic SCSI-2 tape
+drive status = 0
+sense key error = 0
+residue count = 0
+file number = 0
+block number = 0
+Tape block size 0 bytes. Density code 0x0 (default).
+Soft error count since last status=0
+General status bits on (41010000):
+ BOT ONLINE IM_REP_EN
+
+*** read empty block
+dd if=/dev/lto2 of=/tmp/toto count=1
+dd: lecture de `/dev/lto2': Ne peut allouer de la mémoire
+0+0 enregistrements lus
+0+0 enregistrements écrits
+1 octet (1B) copié, 4,82219 seconde, 0,0 kB/s
+
+file number = 0
+block number = 1
+
+*** read file mark
+dd if=/dev/lto2 of=/tmp/toto count=1
+0+0 enregistrements lus
+0+0 enregistrements écrits
+1 octet (1B) copié, 0,167274 seconde, 0,0 kB/s
+
+file number = 1
+block number = 0
+
+ *** write 2 blocks after rewind
+dd if=/dev/zero of=/dev/lto2 count=2
+2+0 enregistrements lus
+2+0 enregistrements écrits
+1024 octets (1,0 kB) copiés, 6,57402 seconde, 0,2 kB/s
+
+file number = 1
+block number = 0
+
+*** write 2 blocks
+file number = 2
+block number = 0
+
+*** rewind and fsr
+file number = 0
+block number = 1
+
+*** rewind and 2x fsr (we have just 2 blocks)
+file number = 0
+block number = 2
+
+*** fsr
+mt: /dev/lto2: Erreur
+file number = 1
+block number = 0
+
+
+ ****************************************************************/
+
+
 #ifdef TEST
 
 int main()
@@ -605,8 +846,16 @@ int main()
    }
 
    faketape *tape = get_tape(fd);
+   tape->write("test", strlen("test")+1);
+   tape->write("test", strlen("test")+1);
    tape->dump();
 
+   tape->weof(1);
+   tape->write("test", strlen("test")+1);
+   tape->write("test", strlen("test")+1);   
+   tape->dump();
+   tape->fsf(2);
+   tape->dump();
    faketape_close(fd);
 
    return 0;
index 47065e530adbde86e923e3cbc3a72beff6c49f88..28d0a0e91780c5dac9592bb028ce4437853ec68c 100644 (file)
@@ -62,20 +62,23 @@ class faketape {
 private:
    int         fd;             /* Our file descriptor */
 
-   int         cur_fd;         /* OS file descriptor */
+   int         cur_fd;         /* OS file descriptor (-1 if not open) */
    off_t       size;           /* size */
 
    bool        atEOF;          /* End of file */
-   bool        atEOM;          /* End of media */
+   bool        atEOT;          /* End of media */
    bool        atEOD;          /* End of data */
+   bool        atBOT;           /* Begin of tape */
+   bool        online;         /* volume online */
 
    POOLMEM     *volume;                /* volume name */
    POOLMEM     *cur_info;      /* volume info */
    POOLMEM     *cur_file;      /* current file name */
 
-   int16_t     max_file;
+   int16_t     last_file;      /* last file of the volume */
    int16_t     current_file;   /* max 65000 files */
    int32_t     current_block;  /* max 4G blocks of 1KB */
+   off_t       max_size;       /* max size of volume */
 
    FTAPE_FORMAT tape_info;
 
@@ -83,9 +86,16 @@ private:
    int read_volinfo();              /* read current volume format */
    int find_maxfile();
    int open_file();
-   int delete_files();
+   int delete_files(int startfile);
+   void check_file() { if (cur_fd == -1) open_file(); };
+   int offline();
+   int close_file();
 
 public:
+   int fsf(int count);
+   int weof(int count);
+   int bsf(int count);
+
    faketape();
    ~faketape();