]> git.sur5r.net Git - bacula/bacula/commitdiff
Implement first cut DCR in SD
authorKern Sibbald <kern@sibbald.com>
Sun, 7 Mar 2004 10:20:24 +0000 (10:20 +0000)
committerKern Sibbald <kern@sibbald.com>
Sun, 7 Mar 2004 10:20:24 +0000 (10:20 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@1113 91ce42f0-d328-0410-95d8-f526ca767f89

30 files changed:
bacula/kernstodo
bacula/src/cats/postgresql.c
bacula/src/cats/sql_get.c
bacula/src/dird/ua_tree.c
bacula/src/findlib/find_one.c
bacula/src/jcr.h
bacula/src/lib/bsys.c
bacula/src/lib/edit.c
bacula/src/lib/message.c
bacula/src/stored/acquire.c
bacula/src/stored/append.c
bacula/src/stored/askdir.c
bacula/src/stored/bcopy.c
bacula/src/stored/bextract.c
bacula/src/stored/block.c
bacula/src/stored/bls.c
bacula/src/stored/bscan.c
bacula/src/stored/btape.c
bacula/src/stored/butil.c
bacula/src/stored/dev.c
bacula/src/stored/dev.h
bacula/src/stored/device.c
bacula/src/stored/dircmd.c
bacula/src/stored/job.c
bacula/src/stored/label.c
bacula/src/stored/mount.c
bacula/src/stored/protos.h
bacula/src/stored/read.c
bacula/src/stored/stored.c
bacula/src/version.h

index 5bc288d7c14d92c468eb38d5ccdbb07efb3aa460..29290c4bc8af7e56f27df0fd44a6bf5a6f89ded0 100644 (file)
@@ -106,9 +106,20 @@ For 1.33
   Do both a long and short form.
 
 - Later:
-- Add a regression test for dbcheck.
-- Add disk seeking on restore.
-- Allow for optional cancelling of SD and FD in case DIR
+- Add John's appended files:
+   Appended = {     /files/server/logs/http/*log   }
+   and such files would be treated as follows.On a FULL backup, they would
+   be backed up like any other file.On an INCREMENTAL backup, where a
+   previous INCREMENTAL or FULL was already in thecatalogue and the length
+   of the file wasgreater than the length of the last backup, only thedata
+   added since the last backup will be dumped.On an INCREMENTAL backup, if
+   the length of the file is less than thelength of the file with the same
+   name last backed up, the completefile is dumped.On Windows systems, with
+   creation date of files, we can be evensmarter about this and not count
+   entirely upon the length.On a restore, the full and all incrementals
+   since it will beapplied in sequence to restore the file.  - Add a
+   regression test for dbcheck.  - Add disk seeking on restore.  - Allow
+   for optional cancelling of SD and FD in case DIR
   gets a fatal error. Requested by Jesse Guardiani <jesse@wingnet.net>
 - Bizarre message: Error: Could not open WriteBootstrap file:
 - Build console in client only build.
index 91b4493743c9973da88369173b8f5bb850b504cd..611ad53a192468ab8e5721534d49bab6f5055d19 100644 (file)
@@ -117,6 +117,7 @@ int
 db_open_database(JCR *jcr, B_DB *mdb)
 {
    int errstat;
+   char port[10];
 
    P(mutex);
    if (mdb->connected) {
@@ -132,12 +133,13 @@ db_open_database(JCR *jcr, B_DB *mdb)
       return 0;
    }
 
+   bsnprintf(port, sizeof(port), "%d", mdb->db_port);
    /* connect to the database */
    mdb->db = PQsetdbLogin(
        mdb->db_address,              /* default = localhost */
-       (char *) mdb->db_port,    /* default port */
-       NULL,                     /* pg options */
-       NULL,                     /* tty, ignored */
+       port,                         /* default port */
+       NULL,                         /* pg options */
+       NULL,                         /* tty, ignored */
        mdb->db_name,                 /* database name */
        mdb->db_user,                 /* login name */
        mdb->db_password);            /* password */
@@ -146,9 +148,9 @@ db_open_database(JCR *jcr, B_DB *mdb)
    if (PQstatus(mdb->db) != CONNECTION_OK) {
    mdb->db = PQsetdbLogin(
        mdb->db_address,              /* default = localhost */
-       (char *) mdb->db_port,    /* default port */
-       NULL,                     /* pg options */
-       NULL,                     /* tty, ignored */
+       port,                         /* default port */
+       NULL,                         /* pg options */
+       NULL,                         /* tty, ignored */
        mdb->db_name,                 /* database name */
        mdb->db_user,                 /* login name */
        mdb->db_password);            /* password */
@@ -290,214 +292,212 @@ int db_sql_query(B_DB *mdb, char *query, DB_RESULT_HANDLER *result_handler, void
 
 POSTGRESQL_ROW my_postgresql_fetch_row(B_DB *mdb) 
 {
-       int            j;
-       POSTGRESQL_ROW row = NULL; // by default, return NULL
+   int           j;
+   POSTGRESQL_ROW row = NULL; // by default, return NULL
 
-        Dmsg0(50, "my_postgresql_fetch_row start\n");
+   Dmsg0(50, "my_postgresql_fetch_row start\n");
 
-       if (mdb->row_number == -1 || mdb->row == NULL) {
+   if (mdb->row_number == -1 || mdb->row == NULL) {
+      Dmsg1(50, "we have need space of %d bytes\n", sizeof(char *) * mdb->num_fields);
 
-                Dmsg1(50, "we have need space of %d bytes\n", sizeof(char *) * mdb->num_fields);
-
-               if (mdb->row != NULL) {
-                        Dmsg0(50, "my_postgresql_fetch_row freeing space\n");
-                       free(mdb->row);
-                       mdb->row = NULL;
-               }
+      if (mdb->row != NULL) {
+              Dmsg0(50, "my_postgresql_fetch_row freeing space\n");
+             free(mdb->row);
+             mdb->row = NULL;
+      }
 
-               mdb->row = (POSTGRESQL_ROW) malloc(sizeof(char *) * mdb->num_fields);
+      mdb->row = (POSTGRESQL_ROW) malloc(sizeof(char *) * mdb->num_fields);
 
-               // now reset the row_number now that we have the space allocated
-               mdb->row_number = 0;
-       }
+      // now reset the row_number now that we have the space allocated
+      mdb->row_number = 0;
+   }
 
-       // if still within the result set
-       if (mdb->row_number < mdb->num_rows) {
-                Dmsg2(50, "my_postgresql_fetch_row row number '%d' is acceptable (0..%d)\n", mdb->row_number, mdb->num_rows);
-               // get each value from this row
-               for (j = 0; j < mdb->num_fields; j++) {
-                       mdb->row[j] = PQgetvalue(mdb->result, mdb->row_number, j);
-                        Dmsg2(50, "my_postgresql_fetch_row field '%d' has value '%s'\n", j, mdb->row[j]);
-               }
-               // increment the row number for the next call
-               mdb->row_number++;
+   // if still within the result set
+   if (mdb->row_number < mdb->num_rows) {
+      Dmsg2(50, "my_postgresql_fetch_row row number '%d' is acceptable (0..%d)\n", mdb->row_number, mdb->num_rows);
+      // get each value from this row
+      for (j = 0; j < mdb->num_fields; j++) {
+             mdb->row[j] = PQgetvalue(mdb->result, mdb->row_number, j);
+              Dmsg2(50, "my_postgresql_fetch_row field '%d' has value '%s'\n", j, mdb->row[j]);
+      }
+      // increment the row number for the next call
+      mdb->row_number++;
 
-               row = mdb->row;
-       } else {
-                Dmsg2(50, "my_postgresql_fetch_row row number '%d' is NOT acceptable (0..%d)\n", mdb->row_number, mdb->num_rows);
-       }
+      row = mdb->row;
+   } else {
+      Dmsg2(50, "my_postgresql_fetch_row row number '%d' is NOT acceptable (0..%d)\n", mdb->row_number, mdb->num_rows);
+   }
 
-        Dmsg1(50, "my_postgresql_fetch_row finishes returning %x\n", row);
+   Dmsg1(50, "my_postgresql_fetch_row finishes returning %x\n", row);
 
-       return row;
+   return row;
 }
 
 int my_postgresql_max_length(B_DB *mdb, int field_num) {
-       //
-       // for a given column, find the max length
-       //
-       int     max_length;
-       int i;
-       int     this_length;
-
-       max_length = 0;
-       for (i = 0; i < mdb->num_rows; i++) {
-               if (PQgetisnull(mdb->result, i, field_num)) {
-                        this_length = 4;        // "NULL"
-               } else {
-                       this_length = strlen(PQgetvalue(mdb->result, i, field_num));
-               }
-                               
-               if (max_length < this_length) {
-                       max_length = this_length;
-               }
-       }
-
-       return max_length;
+   //
+   // for a given column, find the max length
+   //
+   int    max_length;
+   int i;
+   int    this_length;
+
+   max_length = 0;
+   for (i = 0; i < mdb->num_rows; i++) {
+      if (PQgetisnull(mdb->result, i, field_num)) {
+          this_length = 4;        // "NULL"
+      } else {
+         this_length = strlen(PQgetvalue(mdb->result, i, field_num));
+      }
+                     
+      if (max_length < this_length) {
+         max_length = this_length;
+      }
+   }
+
+   return max_length;
 }
 
 POSTGRESQL_FIELD * my_postgresql_fetch_field(B_DB *mdb) 
 {
-       int     i;
-
-        Dmsg0(50, "my_postgresql_fetch_field starts\n");
-       if (mdb->fields == NULL) {
-                Dmsg1(50, "allocating space for %d fields\n", mdb->num_fields);
-               mdb->fields = (POSTGRESQL_FIELD *)
-                                malloc(sizeof(POSTGRESQL_FIELD) * mdb->num_fields);
-
-               for (i = 0; i < mdb->num_fields; i++) {
-                        Dmsg1(50, "filling field %d\n", i);
-                       mdb->fields[i].name           = PQfname(mdb->result, i);
-                       mdb->fields[i].max_length = my_postgresql_max_length(mdb, i);
-                       mdb->fields[i].type       = PQftype(mdb->result, i);
-                       mdb->fields[i].flags      = 0;
-
-                        Dmsg4(50, "my_postgresql_fetch_field finds field '%s' has length='%d' type='%d' and IsNull=%d\n", 
-                          mdb->fields[i].name, mdb->fields[i].max_length, mdb->fields[i].type,
-                          mdb->fields[i].flags);
-               } // end for
-       } // end if
-
-       // increment field number for the next time around
-
-        Dmsg0(50, "my_postgresql_fetch_field finishes\n");
-       return &mdb->fields[mdb->field_number++];
+   int    i;
+
+   Dmsg0(50, "my_postgresql_fetch_field starts\n");
+   if (mdb->fields == NULL) {
+      Dmsg1(50, "allocating space for %d fields\n", mdb->num_fields);
+      mdb->fields = (POSTGRESQL_FIELD *)malloc(sizeof(POSTGRESQL_FIELD) * mdb->num_fields);
+
+      for (i = 0; i < mdb->num_fields; i++) {
+         Dmsg1(50, "filling field %d\n", i);
+        mdb->fields[i].name           = PQfname(mdb->result, i);
+        mdb->fields[i].max_length = my_postgresql_max_length(mdb, i);
+        mdb->fields[i].type       = PQftype(mdb->result, i);
+        mdb->fields[i].flags      = 0;
+
+         Dmsg4(50, "my_postgresql_fetch_field finds field '%s' has length='%d' type='%d' and IsNull=%d\n", 
+           mdb->fields[i].name, mdb->fields[i].max_length, mdb->fields[i].type,
+           mdb->fields[i].flags);
+      } // end for
+   } // end if
+
+   // increment field number for the next time around
+
+   Dmsg0(50, "my_postgresql_fetch_field finishes\n");
+   return &mdb->fields[mdb->field_number++];
 }
 
 void my_postgresql_data_seek(B_DB *mdb, int row) 
 {
-       // set the row number to be returned on the next call
-       // to my_postgresql_fetch_row
-       mdb->row_number = row;
+   // set the row number to be returned on the next call
+   // to my_postgresql_fetch_row
+   mdb->row_number = row;
 }
 
 void my_postgresql_field_seek(B_DB *mdb, int field)
 {
-       mdb->field_number = field;
+   mdb->field_number = field;
 }
 
 int my_postgresql_query(B_DB *mdb, char *query) {
-        Dmsg0(50, "my_postgresql_query started\n");
-       // We are starting a new query.  reset everything.
-       mdb->num_rows     = -1;
-       mdb->row_number   = -1;
-       mdb->field_number = -1;
-
-
-        Dmsg1(50, "my_postgresql_query starts with '%s'\n", query);
-       mdb->result = PQexec(mdb->db, query);
-       mdb->status = PQresultStatus(mdb->result);
-       if (mdb->status == PGRES_TUPLES_OK || mdb->status == PGRES_COMMAND_OK) {
-                Dmsg1(50, "we have a result\n", query);
-
-               // how many fields in the set?
-               mdb->num_fields = (int) PQnfields(mdb->result);
-                Dmsg1(50, "we have %d fields\n", mdb->num_fields);
-
-               mdb->num_rows   = PQntuples(mdb->result);
-                Dmsg1(50, "we have %d rows\n", mdb->num_rows);
-
-               mdb->status = 0;
-       } else {
-                Dmsg1(50, "we failed\n", query);
-               mdb->status = 1;
-       }
+   Dmsg0(50, "my_postgresql_query started\n");
+   // We are starting a new query.  reset everything.
+   mdb->num_rows     = -1;
+   mdb->row_number   = -1;
+   mdb->field_number = -1;
+
+
+   Dmsg1(50, "my_postgresql_query starts with '%s'\n", query);
+   mdb->result = PQexec(mdb->db, query);
+   mdb->status = PQresultStatus(mdb->result);
+   if (mdb->status == PGRES_TUPLES_OK || mdb->status == PGRES_COMMAND_OK) {
+      Dmsg1(50, "we have a result\n", query);
+
+      // how many fields in the set?
+      mdb->num_fields = (int) PQnfields(mdb->result);
+      Dmsg1(50, "we have %d fields\n", mdb->num_fields);
+
+      mdb->num_rows   = PQntuples(mdb->result);
+      Dmsg1(50, "we have %d rows\n", mdb->num_rows);
+
+      mdb->status = 0;
+   } else {
+      Dmsg1(50, "we failed\n", query);
+      mdb->status = 1;
+   }
 
-        Dmsg0(50, "my_postgresql_query finishing\n");
+   Dmsg0(50, "my_postgresql_query finishing\n");
 
-       return mdb->status;
+   return mdb->status;
 }
 
 void my_postgresql_free_result (B_DB *mdb) 
 {
-       if (mdb->result) {
-               PQclear(mdb->result);
-       }
-
-       if (mdb->row) {
-               free(mdb->row);
-               mdb->row = NULL;
-       }
-
-       if (mdb->fields) {
-               free(mdb->fields);
-               mdb->fields = NULL;
-       }
+   if (mdb->result) {
+      PQclear(mdb->result);
+   }
+
+   if (mdb->row) {
+      free(mdb->row);
+      mdb->row = NULL;
+   }
+
+   if (mdb->fields) {
+      free(mdb->fields);
+      mdb->fields = NULL;
+   }
 }
 
 int my_postgresql_currval(B_DB *mdb, char *table_name) 
 {
-       // Obtain the current value of the sequence that
-       // provides the serial value for primary key of the table.
-
-       // currval is local to our session.  It is not affected by
-       // other transactions.
-
-       // Determine the name of the sequence.
-       // PostgreSQL automatically creates a sequence using
-       // <table>_<column>_seq.
-       // At the time of writing, all tables used this format for
-       // for their primary key: <table>id
-       // Except for basefiles which has a primary key on baseid.
-       // Therefore, we need to special case that one table.
-
-       // everything else can use the PostgreSQL formula.
-
-       char      sequence[NAMEDATALEN-1];
-       char      query   [NAMEDATALEN+50];
-       PGresult *result;
-       int       id = 0;
-
-        if (strcasecmp(table_name, "basefiles") == 0) {
-                bstrncpy(sequence, "basefiles_baseid", sizeof(sequence));
-       } else {
-               bstrncpy(sequence, table_name, sizeof(sequence));
-                bstrncat(sequence, "_",        sizeof(sequence));
-               bstrncat(sequence, table_name, sizeof(sequence));
-                bstrncat(sequence, "id",       sizeof(sequence));
-       }
-
-        bstrncat(sequence, "_seq", sizeof(sequence));
-        bsnprintf(query, sizeof(query), "SELECT currval('%s')", sequence);
-
-//      Mmsg(&query, "SELECT currval('%s')", sequence);
-        Dmsg1(50, "my_postgresql_currval invoked with '%s'\n", query);
-       result = PQexec(mdb->db, query);
-
-        Dmsg0(50, "exec done");
-
-       if (PQresultStatus(result) == PGRES_TUPLES_OK) {
-                Dmsg0(50, "getting value");
-               id = atoi(PQgetvalue(result, 0, 0));
-                Dmsg2(50, "got value '%s' which became %d\n", PQgetvalue(result, 0, 0), id);
-       } else {
-                Mmsg1(&mdb->errmsg, _("error fetching currval: %s\n"), PQerrorMessage(mdb->db));
-       }
-
-       PQclear(result);
-
-       return id;
+   // Obtain the current value of the sequence that
+   // provides the serial value for primary key of the table.
+
+   // currval is local to our session. It is not affected by
+   // other transactions.
+
+   // Determine the name of the sequence.
+   // PostgreSQL automatically creates a sequence using
+   // <table>_<column>_seq.
+   // At the time of writing, all tables used this format for
+   // for their primary key: <table>id
+   // Except for basefiles which has a primary key on baseid.
+   // Therefore, we need to special case that one table.
+
+   // everything else can use the PostgreSQL formula.
+
+   char      sequence[NAMEDATALEN-1];
+   char      query   [NAMEDATALEN+50];
+   PGresult *result;
+   int      id = 0;
+
+   if (strcasecmp(table_name, "basefiles") == 0) {
+      bstrncpy(sequence, "basefiles_baseid", sizeof(sequence));
+   } else {
+      bstrncpy(sequence, table_name, sizeof(sequence));
+      bstrncat(sequence, "_",        sizeof(sequence));
+      bstrncat(sequence, table_name, sizeof(sequence));
+      bstrncat(sequence, "id",       sizeof(sequence));
+   }
+
+   bstrncat(sequence, "_seq", sizeof(sequence));
+   bsnprintf(query, sizeof(query), "SELECT currval('%s')", sequence);
+
+// Mmsg(&query, "SELECT currval('%s')", sequence);
+   Dmsg1(50, "my_postgresql_currval invoked with '%s'\n", query);
+   result = PQexec(mdb->db, query);
+
+   Dmsg0(50, "exec done");
+
+   if (PQresultStatus(result) == PGRES_TUPLES_OK) {
+      Dmsg0(50, "getting value");
+      id = atoi(PQgetvalue(result, 0, 0));
+      Dmsg2(50, "got value '%s' which became %d\n", PQgetvalue(result, 0, 0), id);
+   } else {
+      Mmsg1(&mdb->errmsg, _("error fetching currval: %s\n"), PQerrorMessage(mdb->db));
+   }
+
+   PQclear(result);
+
+   return id;
 }
 
 
index 34dcb299f0311f4cfec3f9793b4fae2b2e928435..6d9cad59fc4daa7ce861c139b80a80f8c627c7e8 100644 (file)
@@ -296,7 +296,7 @@ int db_get_job_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr)
    jr->JobStatus = (int)*row[9];
    jr->Type = (int)*row[10];
    jr->Level = (int)*row[11];
-   jr->ClientId = str_to_uint64(row[12]);
+   jr->ClientId = str_to_uint64(row[12]!=NULL?row[12]:(char *)"");
    sql_free_result(mdb);
 
    db_unlock(mdb);
index 7bc68576cf807a66ce5694eec18fe7891c6d1515..7af685a6c1ec931094e150151731bba19a5715c1 100644 (file)
@@ -183,14 +183,21 @@ int insert_tree_handler(void *ctx, int num_fields, char **row)
    } else {
       tree->avail_node = NULL;       /* added node to tree */
    }
-   new_node->FileIndex = atoi(row[2]);
-   new_node->JobId = (JobId_t)str_to_int64(row[3]);
-   new_node->type = type;
-   new_node->extract = true;         /* extract all by default */
-   new_node->hard_link = hard_link;
-   new_node->soft_link = S_ISLNK(statp.st_mode) != 0;
-   if (type == TN_DIR || type == TN_DIR_NLS) {
-      new_node->extract_dir = true;   /* if dir, extract it */
+   /*
+    * If the user has backed up a hard linked file twice, the
+    *  second copy will be a pointer (i.e. hard link will be set),
+    *  so we do not overwrite the original file with a pointer file.
+    */
+   if (!new_node->hard_link || hard_link) {
+      new_node->hard_link = hard_link;
+      new_node->FileIndex = atoi(row[2]);
+      new_node->JobId = (JobId_t)str_to_int64(row[3]);
+      new_node->type = type;
+      new_node->extract = true;         /* extract all by default */
+      new_node->soft_link = S_ISLNK(statp.st_mode) != 0;
+      if (type == TN_DIR || type == TN_DIR_NLS) {
+        new_node->extract_dir = true;   /* if dir, extract it */
+      }
    }
    tree->cnt++;
    return 0;
index cc3f5be47ca5fd9666c22888bfa90f7194a9a482..226bc89e44ec2049ac2329e023bace69fc67b54d 100755 (executable)
@@ -28,8 +28,8 @@
 #include "bacula.h"
 #include "find.h"
 
-extern int32_t name_max;              /* filename max length */
-extern int32_t path_max;              /* path name max length */
+extern int32_t name_max;             /* filename max length */
+extern int32_t path_max;             /* path name max length */
 
 /*
  * Structure for keeping track of hard linked files, we   
@@ -40,11 +40,11 @@ extern int32_t path_max;              /* path name max length */
  */
 struct f_link {
     struct f_link *next;
-    dev_t dev;                        /* device */
-    ino_t ino;                        /* inode with device is unique */
+    dev_t dev;                       /* device */
+    ino_t ino;                       /* inode with device is unique */
     short linkcount;
-    uint32_t FileIndex;               /* Bacula FileIndex of this file */
-    char name[1];                     /* The name */
+    uint32_t FileIndex;              /* Bacula FileIndex of this file */
+    char name[1];                    /* The name */
 };
 
 static void free_dir_ff_pkt(FF_PKT *dir_ff_pkt)
@@ -56,7 +56,7 @@ static void free_dir_ff_pkt(FF_PKT *dir_ff_pkt)
 }
 
 /*
- * Find a single file.                        
+ * Find a single file.                       
  * handle_file is the callback for handling the file.
  * p is the filename
  * parent_device is the device we are currently on 
@@ -65,7 +65,7 @@ static void free_dir_ff_pkt(FF_PKT *dir_ff_pkt)
  */
 int
 find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt), 
-               void *pkt, char *fname, dev_t parent_device, int top_level)
+              void *pkt, char *fname, dev_t parent_device, int top_level)
 {
    struct utimbuf restore_times;
    int rtn_stat;
@@ -97,11 +97,11 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt),
       Dmsg1(300, "Non-directory incremental: %s\n", ff_pkt->fname);
       /* Not a directory */
       if (ff_pkt->statp.st_mtime < ff_pkt->save_time
-          && ((ff_pkt->flags & FO_MTIMEONLY) || 
-              ff_pkt->statp.st_ctime < ff_pkt->save_time)) {
-         /* Incremental option, file not changed */
-         ff_pkt->type = FT_NOCHG;
-         return handle_file(ff_pkt, pkt);
+         && ((ff_pkt->flags & FO_MTIMEONLY) || 
+             ff_pkt->statp.st_ctime < ff_pkt->save_time)) {
+        /* Incremental option, file not changed */
+        ff_pkt->type = FT_NOCHG;
+        return handle_file(ff_pkt, pkt);
       }
    }
 
@@ -123,21 +123,26 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt),
     */
    if (ff_pkt->statp.st_nlink > 1
        && (S_ISREG(ff_pkt->statp.st_mode)
-           || S_ISCHR(ff_pkt->statp.st_mode)
-           || S_ISBLK(ff_pkt->statp.st_mode)
-           || S_ISFIFO(ff_pkt->statp.st_mode)
-           || S_ISSOCK(ff_pkt->statp.st_mode))) {
+          || S_ISCHR(ff_pkt->statp.st_mode)
+          || S_ISBLK(ff_pkt->statp.st_mode)
+          || S_ISFIFO(ff_pkt->statp.st_mode)
+          || S_ISSOCK(ff_pkt->statp.st_mode))) {
 
        struct f_link *lp;
 
       /* Search link list of hard linked files */
       for (lp = ff_pkt->linklist; lp; lp = lp->next)
-         if (lp->ino == ff_pkt->statp.st_ino && lp->dev == ff_pkt->statp.st_dev) {
-             ff_pkt->link = lp->name;
-             ff_pkt->type = FT_LNKSAVED;       /* Handle link, file already saved */
-             ff_pkt->LinkFI = lp->FileIndex;
-             return handle_file(ff_pkt, pkt);
-         }
+        if (lp->ino == ff_pkt->statp.st_ino && lp->dev == ff_pkt->statp.st_dev) {
+             /* If we have already backed up the hard linked file don't do it again */
+            if (strcmp(lp->name, fname) == 0) {
+                Jmsg0(jcr, M_WARNING, 0, _("Attempt to backup hard linked file %s twice ignored.\n"));
+               return 1;             /* ignore */
+            }
+            ff_pkt->link = lp->name;
+            ff_pkt->type = FT_LNKSAVED;       /* Handle link, file already saved */
+            ff_pkt->LinkFI = lp->FileIndex;
+            return handle_file(ff_pkt, pkt);
+        }
 
       /* File not previously dumped. Chain it into our list. */
       lp = (struct f_link *)bmalloc(sizeof(struct f_link) + strlen(fname) +1);
@@ -146,7 +151,7 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt),
       strcpy(lp->name, fname);
       lp->next = ff_pkt->linklist;
       ff_pkt->linklist = lp;
-      ff_pkt->linked = lp;            /* mark saved link */
+      ff_pkt->linked = lp;           /* mark saved link */
    } else {
       ff_pkt->linked = NULL;
    }
@@ -158,16 +163,16 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt),
       sizeleft = ff_pkt->statp.st_size;
 
       /* Don't bother opening empty, world readable files.  Also do not open
-         files when archive is meant for /dev/null.  */
+        files when archive is meant for /dev/null.  */
       if (ff_pkt->null_output_device || (sizeleft == 0
-              && MODE_RALL == (MODE_RALL & ff_pkt->statp.st_mode))) {
-         ff_pkt->type = FT_REGE;
+             && MODE_RALL == (MODE_RALL & ff_pkt->statp.st_mode))) {
+        ff_pkt->type = FT_REGE;
       } else {
-         ff_pkt->type = FT_REG;
+        ff_pkt->type = FT_REG;
       }
       rtn_stat = handle_file(ff_pkt, pkt);
       if (ff_pkt->linked) {
-         ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
+        ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
       }
       return rtn_stat;
 
@@ -178,21 +183,21 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt),
 
       size = readlink(fname, buffer, path_max + name_max + 101);
       if (size < 0) {
-         /* Could not follow link */                             
-         ff_pkt->type = FT_NOFOLLOW;
-         ff_pkt->ff_errno = errno;
-         rtn_stat = handle_file(ff_pkt, pkt);
-         if (ff_pkt->linked) {
-            ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
-         }
-         return rtn_stat;
+        /* Could not follow link */                             
+        ff_pkt->type = FT_NOFOLLOW;
+        ff_pkt->ff_errno = errno;
+        rtn_stat = handle_file(ff_pkt, pkt);
+        if (ff_pkt->linked) {
+           ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
+        }
+        return rtn_stat;
       }
       buffer[size] = 0;
-      ff_pkt->link = buffer;          /* point to link */
-      ff_pkt->type = FT_LNK;          /* got a real link */
+      ff_pkt->link = buffer;         /* point to link */
+      ff_pkt->type = FT_LNK;         /* got a real link */
       rtn_stat = handle_file(ff_pkt, pkt);
       if (ff_pkt->linked) {
-         ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
+        ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
       }
       return rtn_stat;
 
@@ -201,7 +206,7 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt),
       struct dirent *entry, *result;
       char *link;
       int link_len;
-      int len;   
+      int len;  
       int status;
       dev_t our_device = ff_pkt->statp.st_dev;
 
@@ -211,16 +216,16 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt),
        *  in principle, we should be able to access everything.
        */
       if (!have_win32_api() || (ff_pkt->flags & FO_PORTABLE)) {
-         if (access(fname, R_OK) == -1 && geteuid() != 0) {
-            /* Could not access() directory */
-            ff_pkt->type = FT_NOACCESS;
-            ff_pkt->ff_errno = errno;
-            rtn_stat = handle_file(ff_pkt, pkt);
-            if (ff_pkt->linked) {
-               ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
-            }
-            return rtn_stat;
-         }
+        if (access(fname, R_OK) == -1 && geteuid() != 0) {
+           /* Could not access() directory */
+           ff_pkt->type = FT_NOACCESS;
+           ff_pkt->ff_errno = errno;
+           rtn_stat = handle_file(ff_pkt, pkt);
+           if (ff_pkt->linked) {
+              ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
+           }
+           return rtn_stat;
+        }
       }
 
       /* Build a canonical directory name with a trailing slash in link var */
@@ -230,18 +235,18 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt),
       bstrncpy(link, fname, link_len);
       /* Strip all trailing slashes */
       while (len >= 1 && link[len - 1] == '/')
-        len--;
+       len--;
       link[len++] = '/';             /* add back one */
       link[len] = 0;
 
       ff_pkt->link = link;
       if (ff_pkt->incremental &&
-          (ff_pkt->statp.st_mtime < ff_pkt->save_time &&
-           ff_pkt->statp.st_ctime < ff_pkt->save_time)) {
-         /* Incremental option, directory entry not changed */
-         ff_pkt->type = FT_DIRNOCHG;
+         (ff_pkt->statp.st_mtime < ff_pkt->save_time &&
+          ff_pkt->statp.st_ctime < ff_pkt->save_time)) {
+        /* Incremental option, directory entry not changed */
+        ff_pkt->type = FT_DIRNOCHG;
       } else {
-         ff_pkt->type = FT_DIR;
+        ff_pkt->type = FT_DIR;
       }
 
       /*
@@ -262,7 +267,7 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt),
       dir_ff_pkt->excluded_files_list = NULL;
       dir_ff_pkt->excluded_paths_list = NULL;
       dir_ff_pkt->linklist = NULL;
-        
+       
       ff_pkt->link = ff_pkt->fname;     /* reset "link" */
 
       /* 
@@ -270,15 +275,15 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt),
        * user has turned it off for this directory.
        */
       if (ff_pkt->flags & FO_NO_RECURSION) {
-         /* No recursion into this directory */
-         ff_pkt->type = FT_NORECURSE;
-         rtn_stat = handle_file(ff_pkt, pkt);
-         if (ff_pkt->linked) {
-            ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
-         }
-         free(link);
-         free_dir_ff_pkt(dir_ff_pkt);
-         return rtn_stat;
+        /* No recursion into this directory */
+        ff_pkt->type = FT_NORECURSE;
+        rtn_stat = handle_file(ff_pkt, pkt);
+        if (ff_pkt->linked) {
+           ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
+        }
+        free(link);
+        free_dir_ff_pkt(dir_ff_pkt);
+        return rtn_stat;
       }
 
       /* 
@@ -286,16 +291,16 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt),
        * avoid doing so if the user only wants to dump one file system.
        */
       if (!top_level && !(ff_pkt->flags & FO_MULTIFS) &&
-           parent_device != ff_pkt->statp.st_dev) {
-         /* returning here means we do not handle this directory */
-         ff_pkt->type = FT_NOFSCHG;
-         rtn_stat = handle_file(ff_pkt, pkt);
-         if (ff_pkt->linked) {
-            ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
-         }
-         free(link);
-         free_dir_ff_pkt(dir_ff_pkt);
-         return rtn_stat;
+          parent_device != ff_pkt->statp.st_dev) {
+        /* returning here means we do not handle this directory */
+        ff_pkt->type = FT_NOFSCHG;
+        rtn_stat = handle_file(ff_pkt, pkt);
+        if (ff_pkt->linked) {
+           ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
+        }
+        free(link);
+        free_dir_ff_pkt(dir_ff_pkt);
+        return rtn_stat;
       }
       /* 
        * Decend into or "recurse" into the directory to read
@@ -303,15 +308,15 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt),
        */
       errno = 0;
       if ((directory = opendir(fname)) == NULL) {
-         ff_pkt->type = FT_NOOPEN;
-         ff_pkt->ff_errno = errno;
-         rtn_stat = handle_file(ff_pkt, pkt);
-         if (ff_pkt->linked) {
-            ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
-         }
-         free(link);
-         free_dir_ff_pkt(dir_ff_pkt);
-         return rtn_stat;
+        ff_pkt->type = FT_NOOPEN;
+        ff_pkt->ff_errno = errno;
+        rtn_stat = handle_file(ff_pkt, pkt);
+        if (ff_pkt->linked) {
+           ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
+        }
+        free(link);
+        free_dir_ff_pkt(dir_ff_pkt);
+        return rtn_stat;
       }
 
       /*
@@ -322,38 +327,38 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt),
       rtn_stat = 1;
       entry = (struct dirent *)malloc(sizeof(struct dirent) + name_max + 100);
       for ( ; !job_canceled(jcr); ) {
-         char *p, *q;
-         int i;
+        char *p, *q;
+        int i;
 
-         status  = readdir_r(directory, entry, &result);
-         if (status != 0 || result == NULL) {
+        status  = readdir_r(directory, entry, &result);
+        if (status != 0 || result == NULL) {
 //          Dmsg2(99, "readdir returned stat=%d result=0x%x\n",
-//             status, (long)result);
-            break;
-         }
-         ASSERT(name_max+1 > (int)sizeof(struct dirent) + (int)NAMELEN(entry));
-         p = entry->d_name;
+//            status, (long)result);
+           break;
+        }
+        ASSERT(name_max+1 > (int)sizeof(struct dirent) + (int)NAMELEN(entry));
+        p = entry->d_name;
          /* Skip `.', `..', and excluded file names.  */
          if (p[0] == '\0' || (p[0] == '.' && (p[1] == '\0' ||
              (p[1] == '.' && p[2] == '\0')))) {
-            continue;
-         }
-
-         if ((int)NAMELEN(entry) + len >= link_len) {
-             link_len = len + NAMELEN(entry) + 1;
-             link = (char *)brealloc(link, link_len + 1);
-         }
-         q = link + len;
-         for (i=0; i < (int)NAMELEN(entry); i++) {
-            *q++ = *p++;
-         }
-         *q = 0;
-         if (!file_is_excluded(ff_pkt, link)) {
-            rtn_stat = find_one_file(jcr, ff_pkt, handle_file, pkt, link, our_device, 0);
-            if (ff_pkt->linked) {
-               ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
-            }
-         }
+           continue;
+        }
+
+        if ((int)NAMELEN(entry) + len >= link_len) {
+            link_len = len + NAMELEN(entry) + 1;
+            link = (char *)brealloc(link, link_len + 1);
+        }
+        q = link + len;
+        for (i=0; i < (int)NAMELEN(entry); i++) {
+           *q++ = *p++;
+        }
+        *q = 0;
+        if (!file_is_excluded(ff_pkt, link)) {
+           rtn_stat = find_one_file(jcr, ff_pkt, handle_file, pkt, link, our_device, 0);
+           if (ff_pkt->linked) {
+              ff_pkt->linked->FileIndex = ff_pkt->FileIndex;
+           }
+        }
       }
       closedir(directory);
       free(link);
@@ -366,14 +371,14 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt),
        *  the directory modes and dates.  Temp directory values
        *  were used without this record.
        */
-      handle_file(dir_ff_pkt, pkt);       /* handle directory entry */
+      handle_file(dir_ff_pkt, pkt);      /* handle directory entry */
       if (ff_pkt->linked) {
-         ff_pkt->linked->FileIndex = dir_ff_pkt->FileIndex;
+        ff_pkt->linked->FileIndex = dir_ff_pkt->FileIndex;
       }
       free_dir_ff_pkt(dir_ff_pkt);
 
       if (ff_pkt->flags & FO_KEEPATIME) {
-         utime(fname, &restore_times);
+        utime(fname, &restore_times);
       }
       return rtn_stat;
    } /* end check for directory */
@@ -386,8 +391,8 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt),
 #ifdef HAVE_FREEBSD_OS
    /*
     * On FreeBSD, all block devices are character devices, so
-    *   to be able to read a raw disk, we need the check for
-    *   a character device.
+    *  to be able to read a raw disk, we need the check for
+    *  a character device.
 Â Â Â  * crw-r-----  1 root  operator  - 116, 0x00040002 Jun  9 19:32 /dev/ad0s3
 Â Â Â  * crw-r-----  1 root  operator  - 116, 0x00040002 Jun  9 19:32 /dev/rad0s3
     */
@@ -395,9 +400,9 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt),
 #else
    if (top_level && S_ISBLK(ff_pkt->statp.st_mode)) {
 #endif
-      ff_pkt->type = FT_RAW;          /* raw partition */
+      ff_pkt->type = FT_RAW;         /* raw partition */
    } else if (top_level && S_ISFIFO(ff_pkt->statp.st_mode) &&
-              ff_pkt->flags & FO_READFIFO) {
+             ff_pkt->flags & FO_READFIFO) {
       ff_pkt->type = FT_FIFO;
    } else {
       /* The only remaining types are special (character, ...) files */
@@ -420,8 +425,8 @@ int term_find_one(FF_PKT *ff)
       lc = lp;
       lp = lp->next;
       if (lc) {
-         free(lc);
-         count++;
+        free(lc);
+        count++;
       }
    }
    return count;
index a9641222f32311adee3e0fb70b6f11115fb5869c..b9924fe74eb80ccc3b0d5e5dacef40d97c5be267 100644 (file)
@@ -212,7 +212,8 @@ struct JCR {
    JCR *prev_dev;                     /* previous JCR attached to device */
    pthread_cond_t job_start_wait;     /* Wait for FD to start Job */
    int type;
-   DEVRES *device;                    /* device to use */
+   DCR *dcr;                          /* device context record */
+   DEVRES *device;                    /* device resource to use */
    VOLUME_CAT_INFO VolCatInfo;        /* Catalog info for desired volume */
    POOLMEM *job_name;                 /* base Job name (not unique) */
    POOLMEM *fileset_name;             /* FileSet */
@@ -224,24 +225,13 @@ struct JCR {
    VOL_LIST *VolList;                 /* list to read */
    int32_t NumVolumes;                /* number of volumes used */
    int32_t CurVolume;                 /* current volume number */
-   int spool_attributes;              /* set if spooling attributes */
-   int no_attributes;                 /* set if no attributes wanted */
    int label_status;                  /* device volume label status */
    int label_errors;                  /* count of label errors */
-   int session_opened;
-   DEV_RECORD rec;                    /* Read/Write record */
+   bool session_opened;
    long Ticket;                       /* ticket for this job */
-   uint32_t VolFirstIndex;            /* First file index this Volume */
-   uint32_t VolLastIndex;             /* Last file index this Volume */
-   uint32_t FileIndex;                /* Current File Index */
-   uint32_t EndFile;                  /* End file written */
-   uint32_t StartFile;                /* Start write file */
-   uint32_t StartBlock;               /* Start write block */
-   uint32_t EndBlock;                 /* Ending block written */
-   bool NewVol;                       /* set when new Volume mounted */
-   bool WroteVol;                     /* set when Volume written */
-   bool NewFile;                      /* set when EOF written */
    bool ignore_label_errors;          /* ignore Volume label errors */
+   bool spool_attributes;             /* set if spooling attributes */
+   bool no_attributes;                /* set if no attributes wanted */
    int CurVol;                        /* Current Volume count */
 
    uint32_t FileId;                   /* Last file id inserted */
index 4ddb3f4c0029eb1c2fa931dcbd7aab1eef6f3f1f..7251ac9a1f56e3b89840e917f9d297640950656b 100644 (file)
@@ -317,7 +317,7 @@ void create_pid_file(char *dir, const char *progname, int port)
       unlink(mp_chr(fname));                 /* remove stale pid file */
    }
    /* Create new pid file */
-   if ((pidfd = open(mp_chr(fname), O_CREAT|O_TRUNC|O_WRONLY|O_BINARY, 0644)) >= 0) {
+   if ((pidfd = open(mp_chr(fname), O_CREAT|O_TRUNC|O_WRONLY|O_BINARY, 0640)) >= 0) {
       len = sprintf(pidbuf, "%d\n", (int)getpid());
       write(pidfd, pidbuf, len);
       close(pidfd);
index 99184336cdef5059ca425db706209a834fd67290..9647fdf4b39fc1fd89d324b3cd9d1413da742bd1 100644 (file)
@@ -35,6 +35,9 @@ uint64_t str_to_uint64(char *str)
    register char *p = str;
    register uint64_t value = 0;
 
+   if (!p) {
+      return 0;
+   }
    while (B_ISSPACE(*p)) {
       p++;
    }
@@ -52,15 +55,18 @@ int64_t str_to_int64(char *str)
 {
    register char *p = str;
    register int64_t value;
-   int negative = FALSE;
+   bool negative = false;
 
+   if (!p) {
+      return 0;
+   }
    while (B_ISSPACE(*p)) {
       p++;
    }
    if (*p == '+') {
       p++;
    } else if (*p == '-') {
-      negative = TRUE;
+      negative = true;
       p++;
    }
    value = str_to_uint64(p);
index 08ba4dd835438bf5f0841cc074342db0d120cbec..77de72c4e9c85f35861cc24fc1992675dfede68d 100755 (executable)
@@ -380,10 +380,10 @@ static void make_unique_mail_filename(JCR *jcr, POOLMEM **name, DEST *d)
 {
    if (jcr) {
       Mmsg(name, "%s/%s.mail.%s.%d", working_directory, my_name,
-                jcr->Job, (int)d);
+                jcr->Job, (int)(long)d);
    } else {
       Mmsg(name, "%s/%s.mail.%s.%d", working_directory, my_name,
-                my_name, (int)d);
+                my_name, (int)(long)d);
    }
    Dmsg1(200, "mailname=%s\n", *name);
 }
index f9265590655e67ddc22c3626933f0fc286a400ba..c44fd8e3bf802768d31263ccd318cb1365d4cef1 100644 (file)
 
 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
 
+DCR *new_dcr(JCR *jcr, DEVICE *dev)
+{
+   DCR *dcr = (DCR *)malloc(sizeof(DCR));
+   memset(dcr, 0, sizeof(DCR));
+   jcr->dcr = dcr;
+   dcr->jcr = jcr;
+   dcr->dev = dev;
+   dcr->block = new_block(dev);
+   dcr->record = new_record();
+   dcr->spool_fd = -1;
+   return dcr;
+}
+
+void free_dcr(DCR *dcr)
+{
+   if (dcr->block) {
+      free_block(dcr->block);
+   }
+   if (dcr->record) {
+      free_record(dcr->record);
+   }
+   dcr->jcr->dcr = NULL;
+   free(dcr);
+}
+
+
 /********************************************************************* 
  * Acquire device for reading. We permit (for the moment)
  *  only one reader.  We read the Volume label from the block and
@@ -38,7 +64,7 @@ static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
  *  Returns: 0 if failed for any reason
  *          1 if successful
  */
-int acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
+DCR *acquire_device_for_read(JCR *jcr)
 {
    bool vol_ok = false;
    bool tape_previously_mounted;
@@ -46,7 +72,14 @@ int acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
    VOL_LIST *vol;
    int autochanger = 0;
    int i;
-
+   DCR *dcr = jcr->dcr;
+   DEVICE *dev;
+   
+   /* Called for each volume */
+   if (!dcr) {
+      dcr = new_dcr(jcr, jcr->device->dev);
+   }
+   dev = dcr->dev;
    if (device_is_unmounted(dev)) {
       Jmsg(jcr, M_WARNING, 0, _("device %s is BLOCKED due to user unmount.\n"),
         dev_name(dev));
@@ -77,6 +110,7 @@ int acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
       vol = vol->next;
    }
    pm_strcpy(&jcr->VolumeName, vol->VolumeName);
+   bstrncpy(dcr->VolumeName, vol->VolumeName, sizeof(dcr->VolumeName));
 
    for (i=0; i<5; i++) {
       if (job_canceled(jcr)) {
@@ -90,9 +124,9 @@ int acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
        */
       for ( ; !(dev->state & ST_OPENED); ) {
          Dmsg1(120, "bstored: open vol=%s\n", jcr->VolumeName);
-        if (open_dev(dev, jcr->VolumeName, READ_ONLY) < 0) {
+        if (open_dev(dev, dcr->VolumeName, READ_ONLY) < 0) {
             Jmsg(jcr, M_FATAL, 0, _("Open device %s volume %s failed, ERR=%s\n"), 
-               dev_name(dev), jcr->VolumeName, strerror_dev(dev));
+               dev_name(dev), dcr->VolumeName, strerror_dev(dev));
            goto get_out;
         }
          Dmsg1(129, "open_dev %s OK\n", dev_name(dev));
@@ -101,9 +135,9 @@ int acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
        *  correctly possitioned.  Possibly have way user can turn
        *  this optimization (to be implemented) off.
        */
-      dev->state &= ~ST_LABEL;          /* force reread of label */
+      dcr->dev->state &= ~ST_LABEL;          /* force reread of label */
       Dmsg0(200, "calling read-vol-label\n");
-      switch (read_dev_volume_label(jcr, dev, block)) {
+      switch (read_dev_volume_label(jcr, dev, dcr->block)) {
       case VOL_OK:
         vol_ok = true;
         break;                    /* got it */
@@ -165,7 +199,11 @@ get_out:
    P(dev->mutex); 
    unblock_device(dev);
    V(dev->mutex);
-   return vol_ok;
+   if (!vol_ok) {
+      free_dcr(dcr);
+      dcr = NULL;
+   }
+   return dcr;
 }
 
 /*
@@ -178,13 +216,15 @@ get_out:
  *   multiple devices (for files), thus we have our own mutex 
  *   on top of the device mutex.
  */
-DEVICE *acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
+DCR *acquire_device_for_append(JCR *jcr)
 {
    int release = 0;
    bool recycle = false;
    bool do_mount = false;
-   DEVICE *rtn_dev = NULL;
+   DCR *dcr;
+   DEVICE *dev = jcr->device->dev;
 
+   dcr = new_dcr(jcr, dev);
    if (device_is_unmounted(dev)) {
       Jmsg(jcr, M_WARNING, 0, _("device %s is BLOCKED due to user unmount.\n"),
         dev_name(dev));
@@ -207,6 +247,7 @@ DEVICE *acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
        *    dir_find_next_appendable_volume
        */
       pm_strcpy(&jcr->VolumeName, dev->VolHdr.VolName);
+      bstrncpy(dcr->VolumeName, dev->VolHdr.VolName, sizeof(dcr->VolumeName));
       if (!dir_get_volume_info(jcr, GET_VOL_INFO_FOR_WRITE) &&
          !(dir_find_next_appendable_volume(jcr) &&
            strcmp(dev->VolHdr.VolName, jcr->VolumeName) == 0)) { /* wrong tape mounted */
@@ -262,7 +303,7 @@ DEVICE *acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
    }
 
    if (do_mount || recycle) {
-      if (!mount_next_write_volume(jcr, dev, block, release)) {
+      if (!mount_next_write_volume(jcr, dev, dcr->block, release)) {
         if (!job_canceled(jcr)) {
             /* Reduce "noise" -- don't print if job canceled */
             Jmsg(jcr, M_FATAL, 0, _("Could not ready device \"%s\" for append.\n"),
@@ -277,18 +318,21 @@ DEVICE *acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
       jcr->NumVolumes = 1;
    }
    attach_jcr_to_device(dev, jcr);    /* attach jcr to device */
-   rtn_dev = dev;                    /* return device */
+   goto ok_out;
 
 /*
  * If we jump here, it is an error return because
  *  rtn_dev will still be NULL
  */
 get_out:
+   free_dcr(dcr);
+   dcr = NULL;
+ok_out:
    P(dev->mutex); 
    unblock_device(dev);
    V(dev->mutex);
    V(mutex);                         /* unlock other threads */
-   return rtn_dev;
+   return dcr;
 }
 
 /*
@@ -296,8 +340,9 @@ get_out:
  *  the device remains open.
  *
  */
-int release_device(JCR *jcr, DEVICE *dev)
+int release_device(JCR *jcr)
 {
+   DEVICE *dev = jcr->dcr->dev;   
    lock_device(dev);
    Dmsg1(100, "release_device device is %s\n", dev_is_tape(dev)?"tape":"disk");
    if (dev_state(dev, ST_READ)) {
@@ -346,5 +391,7 @@ int release_device(JCR *jcr, DEVICE *dev)
    } else {
       unlock_device(dev);
    }
+   free_dcr(jcr->dcr);
+   jcr->dcr = NULL;
    return 1;
 }
index 6d421306365af470840b4f47395142b4f4a97e7e..0f755ff493fc8a64f2cf2be0031690d84cb84221 100644 (file)
@@ -36,6 +36,12 @@ static bool are_attributes_spooled(JCR *jcr);
 static int begin_attribute_spool(JCR *jcr);
 static int discard_attribute_spool(JCR *jcr);
 static int commit_attribute_spool(JCR *jcr);
+static int open_data_spool_file(JCR *jcr);
+static int close_data_spool_file(JCR *jcr);
+static int begin_data_spool(JCR *jcr);
+static int discard_data_spool(JCR *jcr);
+static int commit_data_spool(JCR *jcr);
+
 
 /* 
  *  Append Data sent from File daemon  
@@ -48,43 +54,39 @@ int do_append_data(JCR *jcr)
    BSOCK *ds;
    BSOCK *fd_sock = jcr->file_bsock;
    bool ok = true;
-   DEVICE *dev = jcr->device->dev;
+   DEVICE *dev;
    DEV_RECORD rec;
    DEV_BLOCK  *block;
+   DCR *dcr;
    
    Dmsg0(10, "Start append data.\n");
 
-   /* Tell File daemon to send data */
-   bnet_fsend(fd_sock, OK_data);
-
-   begin_attribute_spool(jcr);
-
    ds = fd_sock;
 
-   if (!bnet_set_buffer_size(ds, dev->device->max_network_buffer_size, BNET_SETBUF_WRITE)) {
+   if (!bnet_set_buffer_size(ds, jcr->device->max_network_buffer_size, BNET_SETBUF_WRITE)) {
       set_jcr_job_status(jcr, JS_ErrorTerminated);
       Jmsg(jcr, M_FATAL, 0, _("Unable to set network buffer size.\n"));
-      discard_attribute_spool(jcr);
       return 0;
    }
 
-   Dmsg1(20, "Begin append device=%s\n", dev_name(dev));
-
-   block = new_block(dev);
-   memset(&rec, 0, sizeof(rec));
-
    /* 
     * Acquire output device for writing.  Note, after acquiring a
     *  device, we MUST release it, which is done at the end of this
     *  subroutine.
     */
    Dmsg0(100, "just before acquire_device\n");
-   if (!(dev=acquire_device_for_append(jcr, dev, block))) {
+   if (!(dcr=acquire_device_for_append(jcr))) {
       set_jcr_job_status(jcr, JS_ErrorTerminated);
-      free_block(block);
-      discard_attribute_spool(jcr);
       return 0;
    }
+   dev = dcr->dev;
+   block = dcr->block;
+
+   Dmsg1(20, "Begin append device=%s\n", dev_name(dev));
+
+   begin_data_spool(jcr);
+   begin_attribute_spool(jcr);
+
    Dmsg0(100, "Just after acquire_device_for_append\n");
    /*
     * Write Begin Session Record
@@ -96,6 +98,8 @@ int do_append_data(JCR *jcr)
       ok = false;
    }
 
+   /* Tell File daemon to send data */
+   bnet_fsend(fd_sock, OK_data);
 
    /* 
     * Get Data from File daemon, write to device.  To clarify what is
@@ -114,7 +118,7 @@ int do_append_data(JCR *jcr)
     *  file. 1. for the Attributes, 2. for the file data if any, 
     *  and 3. for the MD5 if any.
     */
-   jcr->VolFirstIndex = jcr->VolLastIndex = 0;
+   dcr->VolFirstIndex = dcr->VolLastIndex = 0;
    jcr->run_time = time(NULL);             /* start counting time for rates */
    for (last_file_index = 0; ok && !job_canceled(jcr); ) {
 
@@ -174,7 +178,6 @@ int do_append_data(JCR *jcr)
        *  The data stream is just raw bytes
        */
       while ((n=bget_msg(ds)) > 0 && !job_canceled(jcr)) {
-
         rec.VolSessionId = jcr->VolSessionId;
         rec.VolSessionTime = jcr->VolSessionTime;
         rec.FileIndex = file_index;
@@ -259,17 +262,25 @@ int do_append_data(JCR *jcr)
       }
    }
 
+   if (!ok) {
+      discard_data_spool(jcr);
+   } else {
+      commit_data_spool(jcr);
+   }
+
    Dmsg1(200, "calling release device JobStatus=%d\n", jcr->JobStatus);
    /* Release the device */
-   if (!release_device(jcr, dev)) {
+   if (!release_device(jcr)) {
       Pmsg0(000, _("Error in release_device\n"));
       set_jcr_job_status(jcr, JS_ErrorTerminated);
       ok = false;
    }
 
-   free_block(block);
-
-   commit_attribute_spool(jcr);
+   if (!ok) {
+      discard_attribute_spool(jcr);
+   } else {
+      commit_attribute_spool(jcr);
+   }
 
    dir_send_job_status(jcr);         /* update director */
 
@@ -277,6 +288,70 @@ int do_append_data(JCR *jcr)
    return ok ? 1 : 0;
 }
 
+
+static int begin_data_spool(JCR *jcr)
+{
+   if (jcr->dcr->spool_data) {
+      return open_data_spool_file(jcr);
+   }
+   return 1;
+}
+
+static int discard_data_spool(JCR *jcr)
+{
+   if (jcr->dcr->spool_data && jcr->dcr->spool_fd >= 0) {
+      return close_data_spool_file(jcr);
+   }
+   return 1;
+}
+
+static int commit_data_spool(JCR *jcr)
+{
+   if (jcr->dcr->spool_data && jcr->dcr->spool_fd >= 0) {
+//     despool_data(jcr);
+      return close_data_spool_file(jcr);
+   }
+   return 1;
+}
+
+static void make_unique_data_spool_filename(JCR *jcr, POOLMEM **name)
+{
+   Mmsg(name, "%s/%s.data.spool.%s.%s", working_directory, my_name,
+      jcr->Job, jcr->device->hdr.name);
+}
+
+
+static int open_data_spool_file(JCR *jcr)
+{
+   POOLMEM *name  = get_pool_memory(PM_MESSAGE);
+   int spool_fd;
+
+   make_unique_data_spool_filename(jcr, &name);
+   if ((spool_fd = open(name, O_CREAT|O_TRUNC|O_RDWR|O_BINARY, 0640)) >= 0) {
+      jcr->dcr->spool_fd = spool_fd;
+      jcr->spool_attributes = true;
+   } else {
+      Jmsg(jcr, M_ERROR, 0, "open data spool file %s failed: ERR=%s\n", name, strerror(errno));
+      free_pool_memory(name);
+      return 0;
+    }
+    free_pool_memory(name);
+    return 1;
+}
+
+static int close_data_spool_file(JCR *jcr)
+{
+    POOLMEM *name  = get_pool_memory(PM_MESSAGE);
+
+    make_unique_data_spool_filename(jcr, &name);
+    close(jcr->dcr->spool_fd);
+    jcr->dcr->spool_fd = -1;
+    unlink(name);
+    free_pool_memory(name);
+    return 1;
+}
+
+
 static bool are_attributes_spooled(JCR *jcr)
 {
    return jcr->spool_attributes && jcr->dir_bsock->spool_fd;
index 7573f56a936a16c9595a3bf181642427e8554dd1..ca692e7636dc7545b7ea6440605458e1905a105e 100644 (file)
@@ -76,10 +76,12 @@ int dir_send_job_status(JCR *jcr)
 static int do_get_volume_info(JCR *jcr)
 {
     BSOCK *dir = jcr->dir_bsock;
+    DCR *dcr = jcr->dcr;
     VOLUME_CAT_INFO vol;
     int n;
 
     jcr->VolumeName[0] = 0;          /* No volume */
+    dcr->VolumeName[0] = 0;          /* No volume */
     if (bnet_recv(dir) <= 0) {
        Dmsg0(200, "getvolname error bnet_recv\n");
        Mmsg(&jcr->errmsg, _("Network error on bnet_recv in req_vol_info.\n"));
@@ -102,7 +104,9 @@ static int do_get_volume_info(JCR *jcr)
     }
     unbash_spaces(vol.VolCatName);
     pm_strcpy(&jcr->VolumeName, vol.VolCatName); /* set desired VolumeName */
+    bstrncpy(dcr->VolumeName, vol.VolCatName, sizeof(dcr->VolumeName));
     memcpy(&jcr->VolCatInfo, &vol, sizeof(jcr->VolCatInfo));
+    memcpy(&dcr->VolCatInfo, &vol, sizeof(dcr->VolCatInfo));
     
     Dmsg2(200, "do_reqest_vol_info got slot=%d Volume=%s\n", 
          vol.Slot, vol.VolCatName);
@@ -212,16 +216,17 @@ int dir_update_volume_info(JCR *jcr, DEVICE *dev, int label)
 int dir_create_jobmedia_record(JCR *jcr)
 {
    BSOCK *dir = jcr->dir_bsock;
+   DCR *dcr = jcr->dcr;
 
-   if (!jcr->WroteVol) {
+   if (!dcr->WroteVol) {
       return 1;                      /* nothing written to tape */
    }
 
-   jcr->WroteVol = false;
+   dcr->WroteVol = false;
    bnet_fsend(dir, Create_job_media, jcr->Job, 
-      jcr->VolFirstIndex, jcr->VolLastIndex,
-      jcr->StartFile, jcr->EndFile,
-      jcr->StartBlock, jcr->EndBlock);
+      dcr->VolFirstIndex, dcr->VolLastIndex,
+      dcr->StartFile, dcr->EndFile,
+      dcr->StartBlock, dcr->EndBlock);
    Dmsg1(100, "create_jobmedia(): %s", dir->msg);
    if (bnet_recv(dir) <= 0) {
       Dmsg0(190, "create_jobmedia error bnet_recv\n");
index 761a7d2d7f4e555083553f5c579aa228be3a8c89..73e79945a15beceacfac0ab43d23e9eba3727dfd 100644 (file)
@@ -153,20 +153,18 @@ int main (int argc, char *argv[])
       exit(1);     
    }
    /* For we must now acquire the device for writing */
-   out_block = new_block(out_dev);
    lock_device(out_dev);
    if (open_dev(out_dev, out_jcr->VolumeName, READ_WRITE) < 0) {
       Emsg1(M_FATAL, 0, _("dev open failed: %s\n"), out_dev->errmsg);
       unlock_device(out_dev);
-      free_block(out_block);
       exit(1);
    }
    unlock_device(out_dev);
-   if (!(out_dev=acquire_device_for_append(out_jcr, out_dev, out_block))) {
-      free_block(out_block);
+   if (!acquire_device_for_append(out_jcr)) {
       free_jcr(in_jcr);
       exit(1);
    }
+   out_block = out_jcr->dcr->block;
 
    read_records(in_jcr, in_dev, record_cb, mount_next_read_volume);
    if (!write_block_to_device(out_jcr, out_dev, out_block)) {
@@ -175,7 +173,6 @@ int main (int argc, char *argv[])
 
    Pmsg2(000, _("%u Jobs copied. %u records copied.\n"), jobs, records);
 
-   free_block(out_block);
    term_dev(in_dev);
    term_dev(out_dev);
    free_jcr(in_jcr);
index cbf6e513fe4095db0616da56d332797edeeaab60..dac87a78802e7a8702493691101f0769b61e0c2b 100644 (file)
@@ -222,7 +222,7 @@ static void do_extract(char *devname)
    if (is_bopen(&bfd)) {
       set_attributes(jcr, attr, &bfd);
    }
-   release_device(jcr, dev);
+   release_device(jcr);
 
    free_attr(attr);
    term_dev(dev);
index bc9c09b62bc1ce11931d3286264d1e4e88428c50..5a3edc52eeeb46d913d28a0c9f4aaa5b397d7e4d 100644 (file)
@@ -313,6 +313,8 @@ static int unser_block_header(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
 int write_block_to_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
 {
    int stat = 1;
+   DCR *dcr = jcr->dcr;
+
    lock_device(dev);
 
    /*
@@ -321,7 +323,7 @@ int write_block_to_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
     *  and set new parameters to write this volume   
     * The same applies for if we are in a new file.
     */
-   if (jcr->NewVol || jcr->NewFile) {
+   if (dcr->NewVol || dcr->NewFile) {
       /* Create a jobmedia record for this job */
       if (!dir_create_jobmedia_record(jcr)) {
          Jmsg(jcr, M_ERROR, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
@@ -330,10 +332,10 @@ int write_block_to_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
         unlock_device(dev);
         return 0;
       }
-      if (jcr->NewVol) {
+      if (dcr->NewVol) {
         /* Note, setting a new volume also handles any pending new file */
         set_new_volume_parameters(jcr, dev);
-        jcr->NewFile = false;        /* this handled for new file too */
+        dcr->NewFile = false;        /* this handled for new file too */
       } else {
         set_new_file_parameters(jcr, dev);
       }
@@ -359,6 +361,7 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
    uint32_t wlen;                    /* length to write */
    int hit_max1, hit_max2;
    bool ok;
+   DCR *dcr = jcr->dcr;
 
 #ifdef NO_TAPE_WRITE_TEST
    empty_block(block);
@@ -459,7 +462,7 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
       dir_update_volume_info(jcr, dev, 0);
       if (!dir_create_jobmedia_record(jcr)) {
           Jmsg(jcr, M_ERROR, 0, _("Could not create JobMedia record for Volume=\"%s\" Job=%s\n"),
-              jcr->VolCatInfo.VolCatName, jcr->Job);
+              dcr->VolCatInfo.VolCatName, jcr->Job);
          return 0;
       }
       dev->file_size = 0;            /* reset file size */
@@ -471,7 +474,7 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
         if (mjcr->JobId == 0) {
            continue;                 /* ignore console */
         }
-        mjcr->NewFile = true;        /* set reminder to do set_new_file_params */
+        mjcr->dcr->NewFile = true;   /* set reminder to do set_new_file_params */
       }
       set_new_file_parameters(jcr, dev);
    }
@@ -591,20 +594,20 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
 
    /* Update jcr values */
    if (dev_state(dev, ST_TAPE)) {
-      jcr->EndBlock = dev->EndBlock;
-      jcr->EndFile  = dev->EndFile;
+      dcr->EndBlock = dev->EndBlock;
+      dcr->EndFile  = dev->EndFile;
    } else {
       /* Save address of start of block just written */
-      jcr->EndBlock = (uint32_t)dev->file_addr;
-      jcr->EndFile = (uint32_t)(dev->file_addr >> 32);
+      dcr->EndBlock = (uint32_t)dev->file_addr;
+      dcr->EndFile = (uint32_t)(dev->file_addr >> 32);
    }
-   if (jcr->VolFirstIndex == 0 && block->FirstIndex > 0) {
-      jcr->VolFirstIndex = block->FirstIndex;
+   if (dcr->VolFirstIndex == 0 && block->FirstIndex > 0) {
+      dcr->VolFirstIndex = block->FirstIndex;
    }
    if (block->LastIndex > 0) {
-      jcr->VolLastIndex = block->LastIndex;
+      dcr->VolLastIndex = block->LastIndex;
    }
-   jcr->WroteVol = true;
+   dcr->WroteVol = true;
    dev->file_addr += wlen;           /* update file address */
    dev->file_size += wlen;
 
@@ -640,6 +643,7 @@ int read_block_from_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, bool check_bloc
    int looping;
    uint32_t BlockNumber;
    int retry;
+   DCR *dcr = jcr->dcr;
 
    if (dev_state(dev, ST_EOT)) {
       return 0;
@@ -765,13 +769,13 @@ reread:
 
    /* Update jcr values */
    if (dev->state & ST_TAPE) {
-      jcr->EndBlock = dev->EndBlock;
-      jcr->EndFile  = dev->EndFile;
+      dcr->EndBlock = dev->EndBlock;
+      dcr->EndFile  = dev->EndFile;
    } else {
-      jcr->EndBlock = (uint32_t)dev->file_addr;
-      jcr->EndFile = (uint32_t)(dev->file_addr >> 32);
-      dev->block_num = jcr->EndBlock;
-      dev->file = jcr->EndFile;
+      dcr->EndBlock = (uint32_t)dev->file_addr;
+      dcr->EndFile = (uint32_t)(dev->file_addr >> 32);
+      dev->block_num = dcr->EndBlock;
+      dev->file = dcr->EndFile;
    }
    dev->file_addr += block->block_len;
    dev->file_size += block->block_len;
index f019c41eefd482d8b18248e68b4089c194ae8afd..29f96f0ee38ebb115d26c62936464c27f074d64c 100644 (file)
@@ -234,7 +234,7 @@ Warning, this Volume is a continuation of Volume %s\n",
 
 static void do_close(JCR *jcr)
 {
-   release_device(jcr, dev);
+   release_device(jcr);
    free_attr(attr);
    term_dev(dev);
    free_record(rec);
index 4939581eff47e52c02bbb811dea517e4d69ec5b8..840aad4772fddecd32f6b7759a602d8a265322d8 100644 (file)
@@ -265,15 +265,16 @@ static int bscan_mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
 {
    Dmsg1(100, "Walk attached jcrs. Volume=%s\n", dev->VolCatInfo.VolCatName);
    for (JCR *mjcr=NULL; (mjcr=next_attached_jcr(dev, mjcr)); ) {
+      DCR *dcr = mjcr->dcr;
       if (verbose) {
          Pmsg1(000, _("Create JobMedia for Job %s\n"), mjcr->Job);
       }
       if (dev->state & ST_TAPE) {
-        mjcr->EndBlock = dev->EndBlock;
-        mjcr->EndFile = dev->EndFile;
+        dcr->EndBlock = dev->EndBlock;
+        dcr->EndFile = dev->EndFile;
       } else {
-        mjcr->EndBlock = (uint32_t)dev->file_addr;
-        mjcr->StartBlock = (uint32_t)(dev->file_addr >> 32);
+        dcr->EndBlock = (uint32_t)dev->file_addr;
+        dcr->StartBlock = (uint32_t)(dev->file_addr >> 32);
       }
       if (!create_jobmedia_record(db, mjcr)) {
          Pmsg2(000, _("Could not create JobMedia record for Volume=%s Job=%s\n"),
@@ -305,7 +306,7 @@ static void do_scan()
    detach_jcr_from_device(dev, bjcr);
 
    read_records(bjcr, dev, record_cb, bscan_mount_next_read_volume);
-   release_device(bjcr, dev);
+   release_device(bjcr);
 
    free_attr(attr);
    term_dev(dev);
@@ -314,6 +315,7 @@ static void do_scan()
 static int record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
 {
    JCR *mjcr;
+   DCR *dcr;
    char ec1[30];
 
    if (rec->data_len > 0) {
@@ -392,9 +394,10 @@ static int record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
         }
         /* Reset some JCR variables */
         for (mjcr=NULL; (mjcr=next_attached_jcr(dev, mjcr)); ) {
-           mjcr->VolFirstIndex = mjcr->FileIndex = 0;
-           mjcr->StartBlock = mjcr->EndBlock = 0;
-           mjcr->StartFile = mjcr->EndFile = 0;
+           dcr = mjcr->dcr;
+           dcr->VolFirstIndex = dcr->FileIndex = 0;
+           dcr->StartBlock = dcr->EndBlock = 0;
+           dcr->StartFile = dcr->EndFile = 0;
         }
 
          Pmsg1(000, _("VOL_LABEL: OK for Volume: %s\n"), mr.VolumeName);
@@ -430,16 +433,17 @@ static int record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
 
          /* process label, if Job record exists don't update db */
         mjcr = create_job_record(db, &jr, &label, rec);
+        dcr = mjcr->dcr;
         update_db = save_update_db;
 
         jr.PoolId = pr.PoolId;
         /* Set start positions into JCR */
         if (dev->state & ST_TAPE) {
-           mjcr->StartBlock = dev->block_num;
-           mjcr->StartFile = dev->file;
+           dcr->StartBlock = dev->block_num;
+           dcr->StartFile = dev->file;
         } else {
-           mjcr->StartBlock = (uint32_t)dev->file_addr;
-           mjcr->StartFile = (uint32_t)(dev->file_addr >> 32);
+           dcr->StartBlock = (uint32_t)dev->file_addr;
+           dcr->StartFile = (uint32_t)(dev->file_addr >> 32);
         }
         mjcr->start_time = jr.StartTime;
         mjcr->JobLevel = jr.Level;
@@ -511,7 +515,9 @@ static int record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
          *   them.
          */
         if (update_db) {
-           for (mjcr=NULL; (mjcr=next_attached_jcr(dev, mjcr)); ) {
+           mjcr=next_attached_jcr(dev, NULL);
+           for ( ; mjcr; ) {
+              JCR *njcr; 
               jr.JobId = mjcr->JobId;
               jr.JobStatus = JS_ErrorTerminated;
               jr.JobFiles = mjcr->JobFiles;
@@ -520,10 +526,12 @@ static int record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
               jr.VolSessionTime = mjcr->VolSessionTime;
               jr.JobTDate = (utime_t)mjcr->start_time;
               jr.ClientId = mjcr->ClientId;
-              free_jcr(mjcr);
               if (!db_update_job_end_record(bjcr, db, &jr)) {
                   Pmsg1(0, _("Could not update job record. ERR=%s\n"), db_strerror(db));
               }
+              njcr = mjcr->next_dev;
+              free_jcr(mjcr);
+              mjcr = njcr;
            }
         }
         mr.VolFiles = rec->File;
@@ -550,8 +558,9 @@ static int record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
       }
       return 1;
    }
-   if (mjcr->VolFirstIndex == 0) {
-      mjcr->VolFirstIndex = block->FirstIndex;
+   dcr = mjcr->dcr;
+   if (dcr->VolFirstIndex == 0) {
+      dcr->VolFirstIndex = block->FirstIndex;
    }
 
    /* File Attributes stream */
@@ -656,7 +665,7 @@ static int record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
  *  Called from main free_jcr() routine in src/lib/jcr.c so
  *  that we can do our Director specific cleanup of the jcr.
  */
-static void dird_free_jcr(JCR *jcr)
+static void bscan_free_jcr(JCR *jcr)
 {
    Dmsg0(200, "Start dird free_jcr\n");
 
@@ -671,6 +680,10 @@ static void dird_free_jcr(JCR *jcr)
    if (jcr->RestoreBootstrap) {
       free(jcr->RestoreBootstrap);
    }
+   if (jcr->dcr) {
+      free_dcr(jcr->dcr);
+      jcr->dcr = NULL;
+   }
    Dmsg0(200, "End dird free_jcr\n");
 }
 
@@ -682,7 +695,7 @@ static int create_file_attributes_record(B_DB *db, JCR *mjcr,
                               char *fname, char *lname, int type,
                               char *ap, DEV_RECORD *rec)
 {
-
+   DCR *dcr = mjcr->dcr;
    ar.fname = fname;
    ar.link = lname;
    ar.ClientId = mjcr->ClientId;
@@ -690,10 +703,10 @@ static int create_file_attributes_record(B_DB *db, JCR *mjcr,
    ar.Stream = rec->Stream;
    ar.FileIndex = rec->FileIndex;
    ar.attr = ap;
-   if (mjcr->VolFirstIndex == 0) {
-      mjcr->VolFirstIndex = rec->FileIndex;
+   if (dcr->VolFirstIndex == 0) {
+      dcr->VolFirstIndex = rec->FileIndex;
    }
-   mjcr->FileIndex = rec->FileIndex;
+   dcr->FileIndex = rec->FileIndex;
    mjcr->JobFiles++;
 
    if (!update_db) {
@@ -1013,24 +1026,25 @@ Termination:            %s\n\n"),
 static int create_jobmedia_record(B_DB *db, JCR *mjcr)
 {
    JOBMEDIA_DBR jmr;
+   DCR *dcr = mjcr->dcr;
 
    if (dev->state & ST_TAPE) {
-      mjcr->EndBlock = dev->EndBlock;
-      mjcr->EndFile  = dev->EndFile;
+      dcr->EndBlock = dev->EndBlock;
+      dcr->EndFile  = dev->EndFile;
    } else {
-      mjcr->EndBlock = (uint32_t)dev->file_addr;
-      mjcr->EndFile = (uint32_t)(dev->file_addr >> 32);
+      dcr->EndBlock = (uint32_t)dev->file_addr;
+      dcr->EndFile = (uint32_t)(dev->file_addr >> 32);
    }
 
    memset(&jmr, 0, sizeof(jmr));
    jmr.JobId = mjcr->JobId;
    jmr.MediaId = mr.MediaId;
-   jmr.FirstIndex = mjcr->VolFirstIndex;
-   jmr.LastIndex = mjcr->FileIndex;
-   jmr.StartFile = mjcr->StartFile;
-   jmr.EndFile = mjcr->EndFile;
-   jmr.StartBlock = mjcr->StartBlock;
-   jmr.EndBlock = mjcr->EndBlock;
+   jmr.FirstIndex = dcr->VolFirstIndex;
+   jmr.LastIndex = dcr->FileIndex;
+   jmr.StartFile = dcr->StartFile;
+   jmr.EndFile = dcr->EndFile;
+   jmr.StartBlock = dcr->StartBlock;
+   jmr.EndBlock = dcr->EndBlock;
 
 
    if (!update_db) {
@@ -1094,7 +1108,7 @@ static JCR *create_jcr(JOB_DBR *jr, DEV_RECORD *rec, uint32_t JobId)
     * Transfer as much as possible to the Job JCR. Most important is
     *  the JobId and the ClientId.
     */
-   jobjcr = new_jcr(sizeof(JCR), dird_free_jcr);
+   jobjcr = new_jcr(sizeof(JCR), bscan_free_jcr);
    jobjcr->JobType = jr->Type;
    jobjcr->JobLevel = jr->Level;
    jobjcr->JobStatus = jr->JobStatus;
@@ -1106,6 +1120,7 @@ static JCR *create_jcr(JOB_DBR *jr, DEV_RECORD *rec, uint32_t JobId)
    jobjcr->VolSessionTime = rec->VolSessionTime;
    jobjcr->ClientId = jr->ClientId;
    attach_jcr_to_device(dev, jobjcr);
+   new_dcr(jobjcr, dev);
    return jobjcr;
 }
 
@@ -1121,7 +1136,7 @@ int       dir_send_job_status(JCR *jcr) {return 1;}
 
 int dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev)
 {
-   fprintf(stderr, _("Mount Volume %s on device %s and press return when ready: "),
+   fprintf(stderr, _("Mount Volume \"%s\" on device \"%s\" and press return when ready: "),
       jcr->VolumeName, dev_name(dev));
    getchar();  
    return 1;
index 075e82f5710a6cf7dbc2abba51d8b38475f387ce..62f19c87de5124ec5275593054aea7b55d681aba 100644 (file)
@@ -1692,7 +1692,6 @@ This may take a long time -- hours! ...\n\n");
    /* Use fixed block size to simplify read back */
    min_block_size = dev->min_block_size;
    dev->min_block_size = dev->max_block_size;
-   block = new_block(dev);
 
    /* 
     * Acquire output device for writing.  Note, after acquiring a
@@ -1700,11 +1699,11 @@ This may take a long time -- hours! ...\n\n");
     *  subroutine.
     */
    Dmsg0(100, "just before acquire_device\n");
-   if (!(dev=acquire_device_for_append(jcr, dev, block))) {
+   if (!acquire_device_for_append(jcr)) {
       set_jcr_job_status(jcr, JS_ErrorTerminated);
-      free_block(block);
       return;
    }
+   block = jcr->dcr->block;
 
    Dmsg0(100, "Just after acquire_device_for_append\n");
    /*
@@ -1742,7 +1741,7 @@ This may take a long time -- hours! ...\n\n");
    /* 
     * Generate data as if from File daemon, write to device   
     */
-   jcr->VolFirstIndex = 0;
+   jcr->dcr->VolFirstIndex = 0;
    time(&jcr->run_time);             /* start counting time for rates */
    if (simple) {
       Pmsg0(-1, "Begin writing Bacula records to tape ...\n");
@@ -1868,7 +1867,7 @@ This may take a long time -- hours! ...\n\n");
    }
 
    /* Release the device */
-   if (!release_device(jcr, dev)) {
+   if (!release_device(jcr)) {
       Pmsg0(-1, _("Error in release_device\n"));
       ok = FALSE;
    }
@@ -1880,7 +1879,6 @@ This may take a long time -- hours! ...\n\n");
    do_unfill();
 
    dev->min_block_size = min_block_size;
-   free_block(block);
    free_memory(rec.data);
 }
 
@@ -1969,7 +1967,7 @@ static void do_unfill()
       create_vol_list(jcr);
       close_dev(dev);
       dev->state &= ~ST_READ;
-      if (!acquire_device_for_read(jcr, dev, block)) {
+      if (!acquire_device_for_read(jcr)) {
          Pmsg1(-1, "%s", dev->errmsg);
         goto bail_out;
       }
@@ -2026,7 +2024,7 @@ static void do_unfill()
    }
 
    dev->state &= ~ST_READ;
-   if (!acquire_device_for_read(jcr, dev, block)) {
+   if (!acquire_device_for_read(jcr)) {
       Pmsg1(-1, "%s", dev->errmsg);
       goto bail_out;
    }
@@ -2506,7 +2504,7 @@ int dir_get_volume_info(JCR *jcr, enum get_vol_info_rw    writing)
 
 int dir_create_jobmedia_record(JCR *jcr)
 {
-   jcr->WroteVol = false;
+   jcr->dcr->WroteVol = false;
    return 1;
 }
 
@@ -2598,7 +2596,7 @@ static int my_mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
    create_vol_list(jcr);
    close_dev(dev);
    dev->state &= ~ST_READ; 
-   if (!acquire_device_for_read(jcr, dev, block)) {
+   if (!acquire_device_for_read(jcr)) {
       Pmsg2(0, "Cannot open Dev=%s, Vol=%s\n", dev_name(dev), jcr->VolumeName);
       return 0;
    }
@@ -2607,12 +2605,16 @@ static int my_mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
 
 static void set_volume_name(char *VolName, int volnum) 
 {
+   DCR *dcr = jcr->dcr;
    VolumeName = VolName;
    vol_num = volnum;
    pm_strcpy(&jcr->VolumeName, VolName);
    bstrncpy(dev->VolCatInfo.VolCatName, VolName, sizeof(dev->VolCatInfo.VolCatName));
    bstrncpy(jcr->VolCatInfo.VolCatName, VolName, sizeof(jcr->VolCatInfo.VolCatName));
+   bstrncpy(dcr->VolCatInfo.VolCatName, VolName, sizeof(dcr->VolCatInfo.VolCatName));
+   bstrncpy(dcr->VolumeName, VolName, sizeof(dcr->VolumeName));
    jcr->VolCatInfo.Slot = volnum;
+   dcr->VolCatInfo.Slot = volnum;
 }
 
 /*
index 4c51c407ed2ac7a2ee8958a5e1dca9d679460166..1e1387cf4bd3b2a0594c3cc8fcf7408571bd108c 100644 (file)
@@ -71,7 +71,6 @@ char *rec_state_to_str(DEV_RECORD *rec)
 DEVICE *setup_to_access_device(JCR *jcr, int read_access)
 {
    DEVICE *dev;
-   DEV_BLOCK *block;
    char *p;
    DEVRES *device;
 
@@ -107,17 +106,13 @@ DEVICE *setup_to_access_device(JCR *jcr, int read_access)
    }
    Dmsg0(90, "Device opened for read.\n");
 
-   block = new_block(dev);
-
    create_vol_list(jcr);
 
    if (read_access) {
-      if (!acquire_device_for_read(jcr, dev, block)) {
-        free_block(block);
+      if (!acquire_device_for_read(jcr)) {
         return NULL;
       }
    }
-   free_block(block);
    return dev;
 }
 
@@ -191,6 +186,10 @@ static void my_free_jcr(JCR *jcr)
    if (jcr->VolList) {
       free_vol_list(jcr);
    }  
+   if (jcr->dcr) {
+      free_dcr(jcr->dcr);
+      jcr->dcr = NULL;
+   }
      
    return;
 }
index c0d85f23b27d9294599997a70bda27948994b6d2..8b2a69937a52b0601113a93c5ff5ef8f31116f52 100644 (file)
@@ -101,6 +101,7 @@ init_dev(DEVICE *dev, DEVRES *device)
    struct stat statp;
    int tape, fifo;
    int errstat;
+   DCR *dcr = NULL;
 
    /* Check that device is available */
    if (stat(device->device_name, &statp) < 0) {
@@ -192,7 +193,9 @@ init_dev(DEVICE *dev, DEVRES *device)
       Emsg0(M_FATAL, 0, dev->errmsg);
    }
    dev->fd = -1;
+   dev->attached_dcrs = new dlist(dcr, &dcr->dev_link);
    Dmsg2(29, "init_dev: tape=%d dev_name=%s\n", dev_is_tape(dev), dev->dev_name);
+
    return dev;
 }
 
@@ -1388,6 +1391,10 @@ term_dev(DEVICE *dev)
    pthread_mutex_destroy(&dev->mutex);
    pthread_cond_destroy(&dev->wait);
    pthread_cond_destroy(&dev->wait_next_vol);
+   if (dev->attached_dcrs) {
+      delete dev->attached_dcrs;
+      dev->attached_dcrs = NULL;
+   }
    if (dev->state & ST_MALLOC) {
       free_pool_memory((POOLMEM *)dev);
    }
index 50e03257336e5faa672de5a6a7b7af938864cd38..941b5112ca68ef01255c064b4f24c89d4ed2d83a 100644 (file)
@@ -31,9 +31,9 @@
 
 /* #define NEW_LOCK 1 */
 
-#define new_lock_device(dev)             _new_lock_device(__FILE__, __LINE__, (dev)) 
+#define new_lock_device(dev)            _new_lock_device(__FILE__, __LINE__, (dev)) 
 #define new_lock_device_state(dev,state) _new_lock_device(__FILE__, __LINE__, (dev), (state))
-#define new_unlock_device(dev)           _new_unlock_device(__FILE__, __LINE__, (dev))
+#define new_unlock_device(dev)          _new_unlock_device(__FILE__, __LINE__, (dev))
 
 #define lock_device(d) _lock_device(__FILE__, __LINE__, (d))
 #define unlock_device(d) _unlock_device(__FILE__, __LINE__, (d))
 #define give_back_device_lock(d, p) _give_back_device_lock(__FILE__, __LINE__, (d), (p))
 
 /* Arguments to open_dev() */
-#define READ_WRITE       0
-#define READ_ONLY        1
+#define READ_WRITE      0
+#define READ_ONLY       1
 #define OPEN_READ_WRITE  0
-#define OPEN_READ_ONLY   1
+#define OPEN_READ_ONLY  1
 #define OPEN_WRITE_ONLY  2
 
 /* Generic status bits returned from status_dev() */
-#define BMT_TAPE           (1<<0)     /* is tape device */
-#define BMT_EOF            (1<<1)     /* just read EOF */
-#define BMT_BOT            (1<<2)     /* at beginning of tape */
-#define BMT_EOT            (1<<3)     /* end of tape reached */
-#define BMT_SM             (1<<4)     /* DDS setmark */
-#define BMT_EOD            (1<<5)     /* DDS at end of data */
-#define BMT_WR_PROT        (1<<6)     /* tape write protected */
-#define BMT_ONLINE         (1<<7)     /* tape online */
-#define BMT_DR_OPEN        (1<<8)     /* tape door open */
-#define BMT_IM_REP_EN      (1<<9)     /* immediate report enabled */
+#define BMT_TAPE          (1<<0)     /* is tape device */
+#define BMT_EOF           (1<<1)     /* just read EOF */
+#define BMT_BOT           (1<<2)     /* at beginning of tape */
+#define BMT_EOT           (1<<3)     /* end of tape reached */
+#define BMT_SM            (1<<4)     /* DDS setmark */
+#define BMT_EOD           (1<<5)     /* DDS at end of data */
+#define BMT_WR_PROT       (1<<6)     /* tape write protected */
+#define BMT_ONLINE        (1<<7)     /* tape online */
+#define BMT_DR_OPEN       (1<<8)     /* tape door open */
+#define BMT_IM_REP_EN     (1<<9)     /* immediate report enabled */
 
 
 /* Test capabilities */
 #define dev_cap(dev, cap) ((dev)->capabilities & (cap))
 
 /* Bits for device capabilities */
-#define CAP_EOF            (1<<0)     /* has MTWEOF */
-#define CAP_BSR            (1<<1)     /* has MTBSR */
-#define CAP_BSF            (1<<2)     /* has MTBSF */
-#define CAP_FSR            (1<<3)     /* has MTFSR */
-#define CAP_FSF            (1<<4)     /* has MTFSF */
-#define CAP_EOM            (1<<5)     /* has MTEOM */
-#define CAP_REM            (1<<6)     /* is removable media */
-#define CAP_RACCESS        (1<<7)     /* is random access device */
-#define CAP_AUTOMOUNT      (1<<8)     /* Read device at start to see what is there */
-#define CAP_LABEL          (1<<9)     /* Label blank tapes */
-#define CAP_ANONVOLS       (1<<10)    /* Mount without knowing volume name */
-#define CAP_ALWAYSOPEN     (1<<11)    /* always keep device open */
+#define CAP_EOF           (1<<0)     /* has MTWEOF */
+#define CAP_BSR           (1<<1)     /* has MTBSR */
+#define CAP_BSF           (1<<2)     /* has MTBSF */
+#define CAP_FSR           (1<<3)     /* has MTFSR */
+#define CAP_FSF           (1<<4)     /* has MTFSF */
+#define CAP_EOM           (1<<5)     /* has MTEOM */
+#define CAP_REM           (1<<6)     /* is removable media */
+#define CAP_RACCESS       (1<<7)     /* is random access device */
+#define CAP_AUTOMOUNT     (1<<8)     /* Read device at start to see what is there */
+#define CAP_LABEL         (1<<9)     /* Label blank tapes */
+#define CAP_ANONVOLS      (1<<10)    /* Mount without knowing volume name */
+#define CAP_ALWAYSOPEN    (1<<11)    /* always keep device open */
 #define CAP_AUTOCHANGER    (1<<12)    /* AutoChanger */
 #define CAP_OFFLINEUNMOUNT (1<<13)    /* Offline before unmount */
-#define CAP_STREAM         (1<<14)    /* Stream device */
-#define CAP_BSFATEOM       (1<<15)    /* Backspace file at EOM */
-#define CAP_FASTFSF        (1<<16)    /* Fast forward space file */
-#define CAP_TWOEOF         (1<<17)    /* Write two eofs for EOM */
+#define CAP_STREAM        (1<<14)    /* Stream device */
+#define CAP_BSFATEOM      (1<<15)    /* Backspace file at EOM */
+#define CAP_FASTFSF       (1<<16)    /* Fast forward space file */
+#define CAP_TWOEOF        (1<<17)    /* Write two eofs for EOM */
 #define CAP_CLOSEONPOLL    (1<<18)    /* Close device on polling */
 
 /* Test state */
 #define dev_state(dev, st_state) ((dev)->state & (st_state))
 
 /* Device state bits */
-#define ST_OPENED          (1<<0)     /* set when device opened */
-#define ST_TAPE            (1<<1)     /* is a tape device */  
-#define ST_FILE            (1<<2)     /* is a file device */
-#define ST_FIFO            (1<<3)     /* is a fifo device */
-#define ST_PROG            (1<<4)     /* is a program device */
-#define ST_LABEL           (1<<5)     /* label found */
+#define ST_OPENED         (1<<0)     /* set when device opened */
+#define ST_TAPE           (1<<1)     /* is a tape device */  
+#define ST_FILE           (1<<2)     /* is a file device */
+#define ST_FIFO           (1<<3)     /* is a fifo device */
+#define ST_PROG           (1<<4)     /* is a program device */
+#define ST_LABEL          (1<<5)     /* label found */
 #define ST_MALLOC          (1<<6)     /* dev packet malloc'ed in init_dev() */
-#define ST_APPEND          (1<<7)     /* ready for Bacula append */
-#define ST_READ            (1<<8)     /* ready for Bacula read */
-#define ST_EOT             (1<<9)     /* at end of tape */
-#define ST_WEOT            (1<<10)    /* Got EOT on write */
-#define ST_EOF             (1<<11)    /* Read EOF i.e. zero bytes */
-#define ST_NEXTVOL         (1<<12)    /* Start writing on next volume */
-#define ST_SHORT           (1<<13)    /* Short block read */
+#define ST_APPEND         (1<<7)     /* ready for Bacula append */
+#define ST_READ           (1<<8)     /* ready for Bacula read */
+#define ST_EOT            (1<<9)     /* at end of tape */
+#define ST_WEOT           (1<<10)    /* Got EOT on write */
+#define ST_EOF            (1<<11)    /* Read EOF i.e. zero bytes */
+#define ST_NEXTVOL        (1<<12)    /* Start writing on next volume */
+#define ST_SHORT          (1<<13)    /* Short block read */
 
 /* dev_blocked states (mutually exclusive) */
 #define BST_NOT_BLOCKED       0       /* not blocked */
-#define BST_UNMOUNTED         1       /* User unmounted device */
+#define BST_UNMOUNTED        1       /* User unmounted device */
 #define BST_WAITING_FOR_SYSOP 2       /* Waiting for operator to mount tape */
 #define BST_DOING_ACQUIRE     3       /* Opening/validating/moving tape */
 #define BST_WRITING_LABEL     4       /* Labeling a tape */  
 #define BST_UNMOUNTED_WAITING_FOR_SYSOP 5 /* Closed by user during mount request */
-#define BST_MOUNT             6       /* Mount request */
+#define BST_MOUNT            6       /* Mount request */
 
 /* Volume Catalog Information structure definition */
 struct VOLUME_CAT_INFO {
    /* Media info for the current Volume */
-   uint32_t VolCatJobs;               /* number of jobs on this Volume */
-   uint32_t VolCatFiles;              /* Number of files */
-   uint32_t VolCatBlocks;             /* Number of blocks */
-   uint64_t VolCatBytes;              /* Number of bytes written */
-   uint32_t VolCatMounts;             /* Number of mounts this volume */
-   uint32_t VolCatErrors;             /* Number of errors this volume */
-   uint32_t VolCatWrites;             /* Number of writes this volume */
-   uint32_t VolCatReads;              /* Number of reads this volume */
-   uint64_t VolCatRBytes;             /* Number of bytes read */
-   uint32_t VolCatRecycles;           /* Number of recycles this volume */
-   int32_t  Slot;                     /* Slot in changer */
-   bool     InChanger;                /* Set if vol in current magazine */
-   uint32_t VolCatMaxJobs;            /* Maximum Jobs to write to volume */
-   uint32_t VolCatMaxFiles;           /* Maximum files to write to volume */
-   uint64_t VolCatMaxBytes;           /* Max bytes to write to volume */
+   uint32_t VolCatJobs;              /* number of jobs on this Volume */
+   uint32_t VolCatFiles;             /* Number of files */
+   uint32_t VolCatBlocks;            /* Number of blocks */
+   uint64_t VolCatBytes;             /* Number of bytes written */
+   uint32_t VolCatMounts;            /* Number of mounts this volume */
+   uint32_t VolCatErrors;            /* Number of errors this volume */
+   uint32_t VolCatWrites;            /* Number of writes this volume */
+   uint32_t VolCatReads;             /* Number of reads this volume */
+   uint64_t VolCatRBytes;            /* Number of bytes read */
+   uint32_t VolCatRecycles;          /* Number of recycles this volume */
+   int32_t  Slot;                    /* Slot in changer */
+   bool     InChanger;               /* Set if vol in current magazine */
+   uint32_t VolCatMaxJobs;           /* Maximum Jobs to write to volume */
+   uint32_t VolCatMaxFiles;          /* Maximum files to write to volume */
+   uint64_t VolCatMaxBytes;          /* Max bytes to write to volume */
    uint64_t VolCatCapacityBytes;      /* capacity estimate */
-   uint64_t VolReadTime;              /* time spent reading */
-   uint64_t VolWriteTime;             /* time spent writing this Volume */
-   char VolCatStatus[20];             /* Volume status */
+   uint64_t VolReadTime;             /* time spent reading */
+   uint64_t VolWriteTime;            /* time spent writing this Volume */
+   char VolCatStatus[20];            /* Volume status */
    char VolCatName[MAX_NAME_LENGTH];  /* Desired volume to mount */
-};                
+};               
 
 
 typedef struct s_steal_lock {
-   pthread_t         no_wait_id;      /* id of no wait thread */
-   int               dev_blocked;     /* state */
-   int               dev_prev_blocked; /* previous blocked state */
+   pthread_t        no_wait_id;      /* id of no wait thread */
+   int              dev_blocked;     /* state */
+   int              dev_prev_blocked; /* previous blocked state */
 } bsteal_lock_t;
 
-struct DEVRES;                        /* Device resource defined in stored_conf.h */
+struct DEVRES;                       /* Device resource defined in stored_conf.h */
 
-/* Device structure definition */
+/*
+ * Device structure definition. There is one of these for
+ *  each physical device. Everything here is "global" to 
+ *  that device and effects all jobs using the device.
+ */
 struct DEVICE {
 public:
-   DEVICE *next;                      /* pointer to next open device */
-   DEVICE *prev;                      /* pointer to prev open device */
-   JCR *attached_jcrs;                /* attached JCR list */
-   pthread_mutex_t mutex;             /* access control */
-   pthread_cond_t wait;               /* thread wait variable */
+   DEVICE *next;                     /* pointer to next open device */
+   DEVICE *prev;                     /* pointer to prev open device */
+   JCR *attached_jcrs;               /* attached JCR list */
+   dlist *attached_dcrs;             /* attached DCR list */
+   pthread_mutex_t mutex;            /* access control */
+   pthread_cond_t wait;              /* thread wait variable */
    pthread_cond_t wait_next_vol;      /* wait for tape to be mounted */
-   pthread_t no_wait_id;              /* this thread must not wait */
-   int dev_blocked;                   /* set if we must wait (i.e. change tape) */
-   int dev_prev_blocked;              /* previous blocked state */
-   int num_waiting;                   /* number of threads waiting */
-   int num_writers;                   /* number of writing threads */
-   int use_count;                     /* usage count on this device */
-   int fd;                            /* file descriptor */
-   int capabilities;                  /* capabilities mask */
-   int state;                         /* state mask */
-   int dev_errno;                     /* Our own errno */
-   int mode;                          /* read/write modes */
-   char *dev_name;                    /* device name */
-   char *errmsg;                      /* nicely edited error message */
-   uint32_t block_num;                /* current block number base 0 */
-   uint32_t file;                     /* current file number base 0 */
-   uint64_t file_addr;                /* Current file read/write address */
-   uint64_t file_size;                /* Current file size */
-   uint32_t EndBlock;                 /* last block written */
-   uint32_t EndFile;                  /* last file written */
-   uint32_t min_block_size;           /* min block size */
-   uint32_t max_block_size;           /* max block size */
-   uint64_t max_volume_size;          /* max bytes to put on one volume */
-   uint64_t max_file_size;            /* max file size to put in one file on volume */
-   uint64_t volume_capacity;          /* advisory capacity */
-   uint32_t max_rewind_wait;          /* max secs to allow for rewind */
-   uint32_t max_open_wait;            /* max secs to allow for open */
-   uint32_t max_open_vols;            /* max simultaneous open volumes */
-   utime_t  vol_poll_interval;        /* interval between polling Vol mount */
-   DEVRES *device;                    /* pointer to Device Resource */
-   btimer_t *tid;                     /* timer id */
-
-   VOLUME_CAT_INFO VolCatInfo;        /* Volume Catalog Information */
-   VOLUME_LABEL VolHdr;               /* Actual volume label */
+   pthread_t no_wait_id;             /* this thread must not wait */
+   int dev_blocked;                  /* set if we must wait (i.e. change tape) */
+   int dev_prev_blocked;             /* previous blocked state */
+   int num_waiting;                  /* number of threads waiting */
+   int num_writers;                  /* number of writing threads */
+   int use_count;                    /* usage count on this device */
+   int fd;                           /* file descriptor */
+   int capabilities;                 /* capabilities mask */
+   int state;                        /* state mask */
+   int dev_errno;                    /* Our own errno */
+   int mode;                         /* read/write modes */
+   char *dev_name;                   /* device name */
+   char *errmsg;                     /* nicely edited error message */
+   uint32_t block_num;               /* current block number base 0 */
+   uint32_t file;                    /* current file number base 0 */
+   uint64_t file_addr;               /* Current file read/write address */
+   uint64_t file_size;               /* Current file size */
+   uint32_t EndBlock;                /* last block written */
+   uint32_t EndFile;                 /* last file written */
+   uint32_t min_block_size;          /* min block size */
+   uint32_t max_block_size;          /* max block size */
+   uint64_t max_volume_size;         /* max bytes to put on one volume */
+   uint64_t max_file_size;           /* max file size to put in one file on volume */
+   uint64_t volume_capacity;         /* advisory capacity */
+   uint32_t max_rewind_wait;         /* max secs to allow for rewind */
+   uint32_t max_open_wait;           /* max secs to allow for open */
+   uint32_t max_open_vols;           /* max simultaneous open volumes */
+   utime_t  vol_poll_interval;       /* interval between polling Vol mount */
+   DEVRES *device;                   /* pointer to Device Resource */
+   btimer_t *tid;                    /* timer id */
+
+   VOLUME_CAT_INFO VolCatInfo;       /* Volume Catalog Information */
+   VOLUME_LABEL VolHdr;              /* Actual volume label */
    
    /* Device wait times ***FIXME*** look at durations */
    char BadVolName[MAX_NAME_LENGTH];  /* Last wrong Volume mounted */
-   bool poll;                         /* set to poll Volume */
+   bool poll;                        /* set to poll Volume */
    int min_wait;
    int max_wait;
    int max_num_wait;
@@ -202,13 +207,41 @@ public:
    int num_wait;
 };
 
+/*
+ * Device Context (or Control) Record. 
+ *  There is one of these records for each Job that is using   
+ *  the device. Items in this record are "local" to the Job and
+ *  do not affect other Jobs.
+ */
+struct DCR {
+   dlink dev_link;                   /* link to attach to dev */
+   JCR *jcr;                         /* pointer to JCR */
+   DEVICE *dev;                      /* pointer to device */
+   DEV_BLOCK *block;                 /* pointer to block */
+   DEV_RECORD *record;               /* pointer to record */
+   bool spool_data;                  /* set to spool data */
+   int spool_fd;                     /* fd if spooling */
+   bool NewVol;                      /* set if new Volume mounted */
+   bool WroteVol;                    /* set if Volume written */
+   bool NewFile;                     /* set when EOF written */
+   uint32_t VolFirstIndex;           /* First file index this Volume */
+   uint32_t VolLastIndex;            /* Last file index this Volume */
+   uint32_t FileIndex;               /* Current File Index */
+   uint32_t EndFile;                 /* End file written */
+   uint32_t StartFile;               /* Start write file */
+   uint32_t StartBlock;              /* Start write block */
+   uint32_t EndBlock;                /* Ending block written */
+   char VolumeName[MAX_NAME_LENGTH];  /* Volume name */
+   VOLUME_CAT_INFO VolCatInfo;       /* Catalog info for desired volume */
+};
+
 
 /* Get some definition of function to position
  *  to the end of the medium in MTEOM. System
  *  dependent. Arrgggg!
  */
 #ifndef MTEOM
-#ifdef  MTSEOD
+#ifdef MTSEOD
 #define MTEOM MTSEOD
 #endif
 #ifdef MTEOD
index 51267b4e135c744077656895b631fe081b379ba6..3351c87ecbf718c12ba1ee00c72404749d126718 100644 (file)
@@ -164,14 +164,15 @@ int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
       if (mjcr->JobId == 0) {
         continue;                 /* ignore console */
       }
-      mjcr->NewVol = true;
+      mjcr->dcr->NewVol = true;
       if (jcr != mjcr) {
         pm_strcpy(&mjcr->VolumeName, jcr->VolumeName);  /* get a copy of the new volume */
+        bstrncpy(mjcr->dcr->VolumeName, jcr->VolumeName, sizeof(mjcr->dcr->VolumeName));
       }
    }
 
    /* Clear NewVol now because dir_get_volume_info() already done */
-   jcr->NewVol = false;
+   jcr->dcr->NewVol = false;
    set_new_volume_parameters(jcr, dev);
 
    jcr->run_time += time(NULL) - wait_time; /* correct run time for mount wait */
@@ -196,23 +197,24 @@ int fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
  */
 void set_new_volume_parameters(JCR *jcr, DEVICE *dev) 
 {
-   if (jcr->NewVol && !dir_get_volume_info(jcr, GET_VOL_INFO_FOR_WRITE)) {
+   DCR *dcr = jcr->dcr;
+   if (dcr->NewVol && !dir_get_volume_info(jcr, GET_VOL_INFO_FOR_WRITE)) {
       Jmsg1(jcr, M_ERROR, 0, "%s", jcr->errmsg);
    }
    /* Set new start/end positions */
    if (dev_state(dev, ST_TAPE)) {
-      jcr->StartBlock = dev->block_num;
-      jcr->StartFile = dev->file;
+      dcr->StartBlock = dev->block_num;
+      dcr->StartFile = dev->file;
    } else {
-      jcr->StartBlock = (uint32_t)dev->file_addr;
-      jcr->StartFile  = (uint32_t)(dev->file_addr >> 32);
+      dcr->StartBlock = (uint32_t)dev->file_addr;
+      dcr->StartFile  = (uint32_t)(dev->file_addr >> 32);
    }
    /* Reset indicies */
-   jcr->VolFirstIndex = 0;
-   jcr->VolLastIndex = 0;
+   dcr->VolFirstIndex = 0;
+   dcr->VolLastIndex = 0;
    jcr->NumVolumes++;
-   jcr->NewVol = false;
-   jcr->WroteVol = false;
+   dcr->NewVol = false;
+   dcr->WroteVol = false;
 }
 
 /*
@@ -222,19 +224,21 @@ void set_new_volume_parameters(JCR *jcr, DEVICE *dev)
  */
 void set_new_file_parameters(JCR *jcr, DEVICE *dev) 
 {
+   DCR *dcr = jcr->dcr;
+    
    /* Set new start/end positions */
    if (dev_state(dev, ST_TAPE)) {
-      jcr->StartBlock = dev->block_num;
-      jcr->StartFile = dev->file;
+      dcr->StartBlock = dev->block_num;
+      dcr->StartFile = dev->file;
    } else {
-      jcr->StartBlock = (uint32_t)dev->file_addr;
-      jcr->StartFile  = (uint32_t)(dev->file_addr >> 32);
+      dcr->StartBlock = (uint32_t)dev->file_addr;
+      dcr->StartFile  = (uint32_t)(dev->file_addr >> 32);
    }
    /* Reset indicies */
-   jcr->VolFirstIndex = 0;
-   jcr->VolLastIndex = 0;
-   jcr->NewFile = false;
-   jcr->WroteVol = false;
+   dcr->VolFirstIndex = 0;
+   dcr->VolLastIndex = 0;
+   dcr->NewFile = false;
+   dcr->WroteVol = false;
 }
 
 
index f0b891e95b2360762e537ea1e2f90ed6ba62636b..bd309d569403ae305fde2eef343b0499f5e3ac2b 100644 (file)
@@ -462,6 +462,9 @@ static bool find_device(JCR *jcr, char *dname)
         break;
       }
    }
+   if (found) {
+      jcr->dcr = new_dcr(jcr, device->dev);
+   }
    UnlockRes();
    return found;
 }
index 6c54e6d835bff105fada120bd7678bcd6df2089c..7a9ffa02dc34a277b9ec48caff072d5cc59fbe27 100644 (file)
@@ -103,7 +103,7 @@ int job_cmd(JCR *jcr)
     */
    ojcr = get_jcr_by_full_name(job);
    if (ojcr && !ojcr->authenticated) {
-      Dmsg2(100, "Found ojcr=0x%x Job %s\n", (unsigned)ojcr, job);
+      Dmsg2(100, "Found ojcr=0x%x Job %s\n", (unsigned)(long)ojcr, job);
       free_jcr(ojcr);
    }
    jcr->JobId = JobId;
@@ -362,5 +362,9 @@ void stored_free_jcr(JCR *jcr)
       Emsg0(M_FATAL, 0, _("In free_jcr(), but still attached to device!!!!\n"));
    }
    pthread_cond_destroy(&jcr->job_start_wait);
+   if (jcr->dcr) {
+      free_dcr(jcr->dcr);
+      jcr->dcr = NULL;
+   }
    return;
 }
index 559bb7c2ae02141692b0911091104a420caf3427..e1d5aa609f1b6c68638eb9d437a1a8eeb9b35695 100644 (file)
@@ -443,6 +443,7 @@ int write_volume_label_to_dev(JCR *jcr, DEVRES *device, char *VolName, char *Poo
  */
 void create_session_label(JCR *jcr, DEV_RECORD *rec, int label)
 {
+   DCR *dcr = jcr->dcr;
    ser_declare;
 
    rec->VolSessionId   = jcr->VolSessionId;
@@ -476,10 +477,10 @@ void create_session_label(JCR *jcr, DEV_RECORD *rec, int label)
    if (label == EOS_LABEL) {
       ser_uint32(jcr->JobFiles);
       ser_uint64(jcr->JobBytes);
-      ser_uint32(jcr->StartBlock);
-      ser_uint32(jcr->EndBlock);
-      ser_uint32(jcr->StartFile);
-      ser_uint32(jcr->EndFile);
+      ser_uint32(dcr->StartBlock);
+      ser_uint32(dcr->EndBlock);
+      ser_uint32(dcr->StartFile);
+      ser_uint32(dcr->EndFile);
       ser_uint32(jcr->JobErrors);
 
       /* Added in VerNum 11 */
@@ -496,6 +497,7 @@ void create_session_label(JCR *jcr, DEV_RECORD *rec, int label)
 int write_session_label(JCR *jcr, DEV_BLOCK *block, int label)
 {
    DEVICE *dev = jcr->device->dev;
+   DCR *dcr = jcr->dcr;
    DEV_RECORD *rec;
 
    rec = new_record();
@@ -503,20 +505,20 @@ int write_session_label(JCR *jcr, DEV_BLOCK *block, int label)
    switch (label) {
    case SOS_LABEL:
       if (dev->state & ST_TAPE) {
-        jcr->StartBlock = dev->block_num;
-        jcr->StartFile  = dev->file;
+        dcr->StartBlock = dev->block_num;
+        dcr->StartFile  = dev->file;
       } else {
-        jcr->StartBlock = (uint32_t)dev->file_addr;
-        jcr->StartFile = (uint32_t)(dev->file_addr >> 32);
+        dcr->StartBlock = (uint32_t)dev->file_addr;
+        dcr->StartFile = (uint32_t)(dev->file_addr >> 32);
       }
       break;
    case EOS_LABEL:
       if (dev->state & ST_TAPE) {
-        jcr->EndBlock = dev->EndBlock;
-        jcr->EndFile  = dev->EndFile;
+        dcr->EndBlock = dev->EndBlock;
+        dcr->EndFile  = dev->EndFile;
       } else {
-        jcr->EndBlock = (uint32_t)dev->file_addr;
-        jcr->EndFile = (uint32_t)(dev->file_addr >> 32);
+        dcr->EndBlock = (uint32_t)dev->file_addr;
+        dcr->EndFile = (uint32_t)(dev->file_addr >> 32);
       }
       break;
    default:
index 78f689932daa3ab46797d340b6969c30a2780f24..ced3c8ea71424914ba40d7451246d08521380662 100644 (file)
@@ -406,7 +406,7 @@ int mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
    if (jcr->NumVolumes > 1 && jcr->CurVolume < jcr->NumVolumes) {
       close_dev(dev);
       dev->state &= ~ST_READ; 
-      if (!acquire_device_for_read(jcr, dev, block)) {
+      if (!acquire_device_for_read(jcr)) {
          Jmsg2(jcr, M_FATAL, 0, "Cannot open Dev=%s, Vol=%s\n", dev_name(dev),
               jcr->VolumeName);
         return 0;
@@ -423,7 +423,7 @@ int mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
  */
 void release_volume(JCR *jcr, DEVICE *dev)
 {
-   if (jcr->WroteVol) {
+   if (jcr->dcr->WroteVol) {
       Jmsg0(jcr, M_ERROR, 0, "Hey!!!!! WroteVol non-zero !!!!!\n");
    }
    /* 
index 33025556eaf439b518b72310cd4b7dd5e50ec707..f4c377604701ba2c6aa17eb8967d160412a2a892 100644 (file)
 uint32_t new_VolSessionId();
 
 /* From acquire.c */
-DEVICE  *acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-int      acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-int      release_device(JCR *jcr, DEVICE *dev);
+DCR    *acquire_device_for_append(JCR *jcr);
+DCR    *acquire_device_for_read(JCR *jcr);
+int     release_device(JCR *jcr);
+DCR    *new_dcr(JCR *jcr, DEVICE *dev);
+void    free_dcr(DCR *dcr);
 
 /* From askdir.c */
 enum get_vol_info_rw {
    GET_VOL_INFO_FOR_WRITE,
    GET_VOL_INFO_FOR_READ
 };
-int     dir_get_volume_info(JCR *jcr, enum get_vol_info_rw);
-int     dir_find_next_appendable_volume(JCR *jcr);
-int     dir_update_volume_info(JCR *jcr, DEVICE *dev, int label);
-int     dir_ask_sysop_to_create_appendable_volume(JCR *jcr, DEVICE *dev);
-int     dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev);
-int     dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec);
-int     dir_send_job_status(JCR *jcr);
-int     dir_create_jobmedia_record(JCR *jcr);
+int    dir_get_volume_info(JCR *jcr, enum get_vol_info_rw);
+int    dir_find_next_appendable_volume(JCR *jcr);
+int    dir_update_volume_info(JCR *jcr, DEVICE *dev, int label);
+int    dir_ask_sysop_to_create_appendable_volume(JCR *jcr, DEVICE *dev);
+int    dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev);
+int    dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec);
+int    dir_send_job_status(JCR *jcr);
+int    dir_create_jobmedia_record(JCR *jcr);
 
 /* authenticate.c */
-int     authenticate_director(JCR *jcr);
-int     authenticate_filed(JCR *jcr);
+int    authenticate_director(JCR *jcr);
+int    authenticate_filed(JCR *jcr);
 
 /* From block.c */
-void    dump_block(DEV_BLOCK *b, char *msg);
+void   dump_block(DEV_BLOCK *b, char *msg);
 DEV_BLOCK *new_block(DEVICE *dev);
 DEV_BLOCK *dup_block(DEV_BLOCK *eblock);
-void    init_block_write(DEV_BLOCK *block);
-void    empty_block(DEV_BLOCK *block);
-void    free_block(DEV_BLOCK *block);
-int     write_block_to_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-int     write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-void    print_block_read_errors(JCR *jcr, DEV_BLOCK *block);
+void   init_block_write(DEV_BLOCK *block);
+void   empty_block(DEV_BLOCK *block);
+void   free_block(DEV_BLOCK *block);
+int    write_block_to_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+int    write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+void   print_block_read_errors(JCR *jcr, DEV_BLOCK *block);
 
 #define CHECK_BLOCK_NUMBERS    true
 #define NO_BLOCK_NUMBER_CHECK  false
-int     read_block_from_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, bool check_block_numbers);
-int     read_block_from_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, bool check_block_numbers);
+int    read_block_from_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, bool check_block_numbers);
+int    read_block_from_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, bool check_block_numbers);
 
 /* From butil.c -- utilities for SD tool programs */
-void    print_ls_output(char *fname, char *link, int type, struct stat *statp);
+void   print_ls_output(char *fname, char *link, int type, struct stat *statp);
 JCR    *setup_jcr(char *name, char *device, BSR *bsr, char *VolumeName);
 DEVICE *setup_to_access_device(JCR *jcr, int read_access);
-void    display_tape_error_status(JCR *jcr, DEVICE *dev);
+void   display_tape_error_status(JCR *jcr, DEVICE *dev);
 DEVRES *find_device_res(char *device_name, int read_access);
 
 
 /* From dev.c */
-DEVICE  *init_dev(DEVICE *dev, DEVRES *device);
-int      open_dev(DEVICE *dev, char *VolName, int mode);
-void     close_dev(DEVICE *dev);
-void     force_close_dev(DEVICE *dev);
-int      truncate_dev(DEVICE *dev);
-void     term_dev(DEVICE *dev);
-char *   strerror_dev(DEVICE *dev);
-void     clrerror_dev(DEVICE *dev, int func);
-int      update_pos_dev(DEVICE *dev);
-int      rewind_dev(DEVICE *dev);
-int      load_dev(DEVICE *dev);
-int      offline_dev(DEVICE *dev);
-int      flush_dev(DEVICE *dev);
-int      weof_dev(DEVICE *dev, int num);
-int      write_block(DEVICE *dev);
-int      write_dev(DEVICE *dev, char *buf, size_t len);
-int      read_dev(DEVICE *dev, char *buf, size_t len);
+DEVICE *init_dev(DEVICE *dev, DEVRES *device);
+int     open_dev(DEVICE *dev, char *VolName, int mode);
+void    close_dev(DEVICE *dev);
+void    force_close_dev(DEVICE *dev);
+int     truncate_dev(DEVICE *dev);
+void    term_dev(DEVICE *dev);
+char *  strerror_dev(DEVICE *dev);
+void    clrerror_dev(DEVICE *dev, int func);
+int     update_pos_dev(DEVICE *dev);
+int     rewind_dev(DEVICE *dev);
+int     load_dev(DEVICE *dev);
+int     offline_dev(DEVICE *dev);
+int     flush_dev(DEVICE *dev);
+int     weof_dev(DEVICE *dev, int num);
+int     write_block(DEVICE *dev);
+int     write_dev(DEVICE *dev, char *buf, size_t len);
+int     read_dev(DEVICE *dev, char *buf, size_t len);
 uint32_t status_dev(DEVICE *dev);
-int      eod_dev(DEVICE *dev);
-int      fsf_dev(DEVICE *dev, int num);
-int      fsr_dev(DEVICE *dev, int num);
-int      bsf_dev(DEVICE *dev, int num);
-int      bsr_dev(DEVICE *dev, int num);
-void     attach_jcr_to_device(DEVICE *dev, JCR *jcr);
-void     detach_jcr_from_device(DEVICE *dev, JCR *jcr);
-JCR     *next_attached_jcr(DEVICE *dev, JCR *jcr);
-int      dev_can_write(DEVICE *dev);
-int      offline_or_rewind_dev(DEVICE *dev);
-int      reposition_dev(DEVICE *dev, uint32_t file, uint32_t block);
-void     init_dev_wait_timers(DEVICE *dev);
-bool     double_dev_wait_time(DEVICE *dev);
+int     eod_dev(DEVICE *dev);
+int     fsf_dev(DEVICE *dev, int num);
+int     fsr_dev(DEVICE *dev, int num);
+int     bsf_dev(DEVICE *dev, int num);
+int     bsr_dev(DEVICE *dev, int num);
+void    attach_jcr_to_device(DEVICE *dev, JCR *jcr);
+void    detach_jcr_from_device(DEVICE *dev, JCR *jcr);
+JCR    *next_attached_jcr(DEVICE *dev, JCR *jcr);
+int     dev_can_write(DEVICE *dev);
+int     offline_or_rewind_dev(DEVICE *dev);
+int     reposition_dev(DEVICE *dev, uint32_t file, uint32_t block);
+void    init_dev_wait_timers(DEVICE *dev);
+bool    double_dev_wait_time(DEVICE *dev);
 
 
 /* Get info about device */
-char *   dev_name(DEVICE *dev);
-char *   dev_vol_name(DEVICE *dev);
+char *  dev_name(DEVICE *dev);
+char *  dev_vol_name(DEVICE *dev);
 uint32_t dev_block(DEVICE *dev);
 uint32_t dev_file(DEVICE *dev);
-int      dev_is_tape(DEVICE *dev);
+int     dev_is_tape(DEVICE *dev);
 
 /* From device.c */
-int      open_device(JCR *jcr, DEVICE *dev);
-int      first_open_device(DEVICE *dev);
-int      fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-void     _lock_device(char *file, int line, DEVICE *dev);
-void     _unlock_device(char *file, int line, DEVICE *dev);
-void     _block_device(char *file, int line, DEVICE *dev, int state);
-void     _unblock_device(char *file, int line, DEVICE *dev);
-void     _steal_device_lock(char *file, int line, DEVICE *dev, bsteal_lock_t *hold, int state);
-void     _give_back_device_lock(char *file, int line, DEVICE *dev, bsteal_lock_t *hold);
-void     set_new_volume_parameters(JCR *jcr, DEVICE *dev);
-void     set_new_file_parameters(JCR *jcr, DEVICE *dev); 
-int      device_is_unmounted(DEVICE *dev);
+int     open_device(JCR *jcr, DEVICE *dev);
+int     first_open_device(DEVICE *dev);
+int     fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+void    _lock_device(char *file, int line, DEVICE *dev);
+void    _unlock_device(char *file, int line, DEVICE *dev);
+void    _block_device(char *file, int line, DEVICE *dev, int state);
+void    _unblock_device(char *file, int line, DEVICE *dev);
+void    _steal_device_lock(char *file, int line, DEVICE *dev, bsteal_lock_t *hold, int state);
+void    _give_back_device_lock(char *file, int line, DEVICE *dev, bsteal_lock_t *hold);
+void    set_new_volume_parameters(JCR *jcr, DEVICE *dev);
+void    set_new_file_parameters(JCR *jcr, DEVICE *dev); 
+int     device_is_unmounted(DEVICE *dev);
 
 /* From dircmd.c */
-void     *connection_request(void *arg); 
+void    *connection_request(void *arg); 
 
 
 /* From fd_cmds.c */
-void     run_job(JCR *jcr);
+void    run_job(JCR *jcr);
 
 /* From job.c */
-void     stored_free_jcr(JCR *jcr);
-void     connection_from_filed(void *arg);     
-void     handle_filed_connection(BSOCK *fd, char *job_name);
+void    stored_free_jcr(JCR *jcr);
+void    connection_from_filed(void *arg);     
+void    handle_filed_connection(BSOCK *fd, char *job_name);
 
 /* From label.c */
-int      read_dev_volume_label(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-void     create_session_label(JCR *jcr, DEV_RECORD *rec, int label);
-void     create_volume_label(DEVICE *dev, char *VolName, char *PoolName);
-int      write_volume_label_to_dev(JCR *jcr, DEVRES *device, char *VolName, char *PoolName);
-int      write_session_label(JCR *jcr, DEV_BLOCK *block, int label);
-int      write_volume_label_to_block(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-void     dump_volume_label(DEVICE *dev);
-void     dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose);
-int      unser_volume_label(DEVICE *dev, DEV_RECORD *rec);
-int      unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec);
+int     read_dev_volume_label(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+void    create_session_label(JCR *jcr, DEV_RECORD *rec, int label);
+void    create_volume_label(DEVICE *dev, char *VolName, char *PoolName);
+int     write_volume_label_to_dev(JCR *jcr, DEVRES *device, char *VolName, char *PoolName);
+int     write_session_label(JCR *jcr, DEV_BLOCK *block, int label);
+int     write_volume_label_to_block(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+void    dump_volume_label(DEVICE *dev);
+void    dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose);
+int     unser_volume_label(DEVICE *dev, DEV_RECORD *rec);
+int     unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec);
 
 /* From match_bsr.c */
-int      match_bsr(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec, 
-              SESSION_LABEL *sesrec);
-int      match_bsr_block(BSR *bsr, DEV_BLOCK *block);
-void     position_bsr_block(BSR *bsr, DEV_BLOCK *block);
-BSR     *find_next_bsr(BSR *root_bsr, DEVICE *dev);
-bool     match_set_eof(BSR *bsr, DEV_RECORD *rec);
+int     match_bsr(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec, 
+             SESSION_LABEL *sesrec);
+int     match_bsr_block(BSR *bsr, DEV_BLOCK *block);
+void    position_bsr_block(BSR *bsr, DEV_BLOCK *block);
+BSR    *find_next_bsr(BSR *root_bsr, DEVICE *dev);
+bool    match_set_eof(BSR *bsr, DEV_RECORD *rec);
 
 /* From mount.c */
-int      mount_next_write_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, int release);
-int      mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-void     release_volume(JCR *jcr, DEVICE *dev);
-void     mark_volume_in_error(JCR *jcr, DEVICE *dev);
+int     mount_next_write_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, int release);
+int     mount_next_read_volume(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+void    release_volume(JCR *jcr, DEVICE *dev);
+void    mark_volume_in_error(JCR *jcr, DEVICE *dev);
 
 /* From autochanger.c */
-int      autoload_device(JCR *jcr, DEVICE *dev, int writing, BSOCK *dir);
-int      autochanger_list(JCR *jcr, DEVICE *dev, BSOCK *dir);
-void     invalidate_slot_in_catalog(JCR *jcr, DEVICE *dev);
+int     autoload_device(JCR *jcr, DEVICE *dev, int writing, BSOCK *dir);
+int     autochanger_list(JCR *jcr, DEVICE *dev, BSOCK *dir);
+void    invalidate_slot_in_catalog(JCR *jcr, DEVICE *dev);
 
 
 /* From parse_bsr.c */
-BSR     *parse_bsr(JCR *jcr, char *lf);
-void     dump_bsr(BSR *bsr, bool recurse);
-void     free_bsr(BSR *bsr);
+BSR    *parse_bsr(JCR *jcr, char *lf);
+void    dump_bsr(BSR *bsr, bool recurse);
+void    free_bsr(BSR *bsr);
 VOL_LIST *new_vol();
-int      add_vol(JCR *jcr, VOL_LIST *vol);
-void     free_vol_list(JCR *jcr);
-void     create_vol_list(JCR *jcr);
+int     add_vol(JCR *jcr, VOL_LIST *vol);
+void    free_vol_list(JCR *jcr);
+void    create_vol_list(JCR *jcr);
 
 /* From record.c */
-char    *FI_to_ascii(int fi);
-char    *stream_to_ascii(int stream, int fi);
-int      write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
-int      can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
-int      read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec); 
+char   *FI_to_ascii(int fi);
+char   *stream_to_ascii(int stream, int fi);
+int     write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
+int     can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
+int     read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec); 
 DEV_RECORD *new_record();
-void     free_record(DEV_RECORD *rec);
+void    free_record(DEV_RECORD *rec);
 
 /* From read_record.c */
 int read_records(JCR *jcr,  DEVICE *dev, 
index 1285e5a0d785a33e778eb9858c19c930e22d58d4..0e7dbeb8caf262036f85ffd107cade06d04a96f1 100644 (file)
@@ -34,6 +34,7 @@ static int record_cb(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec);
 
 /* Responses sent to the File daemon */
 static char OK_data[]    = "3000 OK data\n";
+static char FD_error[]   = "3000 error\n";
 static char rec_header[] = "rechdr %ld %ld %ld %ld %ld";
 
 /* 
@@ -47,29 +48,26 @@ int do_read_data(JCR *jcr)
    int ok = TRUE;
    DEVICE *dev;
    DEV_BLOCK *block;
+   DCR *dcr;
    
    Dmsg0(20, "Start read data.\n");
 
    dev = jcr->device->dev;
 
-   /* Tell File daemon we will send data */
-   bnet_fsend(fd, OK_data);
    Dmsg1(10, "bstored>filed: %s\n", fd->msg);
 
-   if (!bnet_set_buffer_size(fd, dev->device->max_network_buffer_size, BNET_SETBUF_WRITE)) {
+   if (!bnet_set_buffer_size(fd, jcr->device->max_network_buffer_size, BNET_SETBUF_WRITE)) {
       return 0;
    }
 
 
    Dmsg1(20, "Begin read device=%s\n", dev_name(dev));
 
-   block = new_block(dev);
-
    create_vol_list(jcr);
    if (jcr->NumVolumes == 0) {
       Jmsg(jcr, M_FATAL, 0, _("No Volume names found for restore.\n"));
-      free_block(block);
       free_vol_list(jcr);
+      bnet_fsend(fd, FD_error);
       return 0;
    }
 
@@ -81,22 +79,24 @@ int do_read_data(JCR *jcr)
    /* 
     * Ready device for reading, and read records
     */
-   if (!acquire_device_for_read(jcr, dev, block)) {
-      free_block(block);
+   if (!acquire_device_for_read(jcr)) {
       free_vol_list(jcr);
       return 0;
    }
 
+   block = dcr->block;
+
+   /* Tell File daemon we will send data */
+   bnet_fsend(fd, OK_data);
    ok = read_records(jcr, dev, record_cb, mount_next_read_volume);
 
    /* Send end of data to FD */
    bnet_sig(fd, BNET_EOD);
 
-   if (!release_device(jcr, dev)) {
+   if (!release_device(jcr)) {
       ok = FALSE;
    }
    
-   free_block(block);
    free_vol_list(jcr);
    Dmsg0(30, "Done reading.\n");
    return ok ? 1 : 0;
index 54d8e2524d469b0de38c4da58b7ca066b73ac2fa..ae82a14028bba516c2e2d3ee7c439f59e12851c9 100644 (file)
@@ -304,6 +304,7 @@ static void *device_allocation(void *arg)
          Emsg1(M_ERROR, 0, _("Could not initialize %s\n"), device->device_name);
         continue;
       }
+
       if (device->cap_bits & CAP_ALWAYSOPEN) {
          Dmsg1(20, "calling first_open_device %s\n", device->device_name);
         if (!first_open_device(device->dev)) {
@@ -312,11 +313,12 @@ static void *device_allocation(void *arg)
       }
       if (device->cap_bits & CAP_AUTOMOUNT && device->dev && 
          device->dev->state & ST_OPENED) {
-        DEV_BLOCK *block;
         JCR *jcr;
-        block = new_block(device->dev);
+        DCR *dcr;
         jcr = new_jcr(sizeof(JCR), stored_free_jcr);
-        switch (read_dev_volume_label(jcr, device->dev, block)) {
+        jcr->device = device;
+        dcr = new_dcr(jcr, device->dev);
+        switch (read_dev_volume_label(jcr, device->dev, dcr->block)) {
            case VOL_OK:
               break;
            default:
@@ -324,7 +326,6 @@ static void *device_allocation(void *arg)
               break;
         }
         free_jcr(jcr);
-        free_block(block);
       }
    } 
    UnlockRes();
index f50e7891dfb994098e8d1eb3961da7a96b6a82bb..0ab3d658f278646d9b8f1755041e075ec58d7af5 100644 (file)
@@ -2,8 +2,8 @@
 #undef  VERSION
 #define VERSION "1.33.4"
 #define VSTRING "1"
-#define BDATE   "02 Mar 2004"
-#define LSMDATE "02Mar04"
+#define BDATE   "06 Mar 2004"
+#define LSMDATE "06Mar04"
 
 /* Debug flags */
 #undef  DEBUG