]> git.sur5r.net Git - bacula/bacula/commitdiff
kes This patch prevents the 'status dir' command from trying to use a scratch
authorKern Sibbald <kern@sibbald.com>
Sun, 2 Dec 2007 18:04:07 +0000 (18:04 +0000)
committerKern Sibbald <kern@sibbald.com>
Sun, 2 Dec 2007 18:04:07 +0000 (18:04 +0000)
     volume and possibly moving it from one pool to another.  This patch fixes
     bug #1019.

git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/branches/Branch-2.2@6012 91ce42f0-d328-0410-95d8-f526ca767f89

35 files changed:
bacula/patches/2.2.4-ansi-label.patch [deleted file]
bacula/patches/2.2.4-lost-block.patch [deleted file]
bacula/patches/2.2.4-parse-command.patch [deleted file]
bacula/patches/2.2.4-poll-mount.patch [deleted file]
bacula/patches/2.2.4-replace.patch [deleted file]
bacula/patches/2.2.4-restore.patch [deleted file]
bacula/patches/2.2.4-sd-auth-fail.patch [deleted file]
bacula/patches/2.2.4-sql.patch [deleted file]
bacula/patches/2.2.4-verify.patch [deleted file]
bacula/patches/2.2.5-deamon.patch [deleted file]
bacula/patches/2.2.5-hb.patch [deleted file]
bacula/patches/2.2.5-lastwritten.patch [deleted file]
bacula/patches/2.2.5-nextvol.patch [deleted file]
bacula/patches/2.2.5-postgresql-errors.patch [deleted file]
bacula/patches/2.2.5-tray-monitor.patch [deleted file]
bacula/patches/2.2.5-verify-loop.patch [deleted file]
bacula/patches/2.2.6-scratch.patch [new file with mode: 0644]
bacula/patches/2.2.x/2.2.4-ansi-label.patch [new file with mode: 0644]
bacula/patches/2.2.x/2.2.4-lost-block.patch [new file with mode: 0644]
bacula/patches/2.2.x/2.2.4-parse-command.patch [new file with mode: 0644]
bacula/patches/2.2.x/2.2.4-poll-mount.patch [new file with mode: 0644]
bacula/patches/2.2.x/2.2.4-replace.patch [new file with mode: 0644]
bacula/patches/2.2.x/2.2.4-restore.patch [new file with mode: 0644]
bacula/patches/2.2.x/2.2.4-sd-auth-fail.patch [new file with mode: 0644]
bacula/patches/2.2.x/2.2.4-sql.patch [new file with mode: 0644]
bacula/patches/2.2.x/2.2.4-verify.patch [new file with mode: 0644]
bacula/patches/2.2.x/2.2.5-deamon.patch [new file with mode: 0644]
bacula/patches/2.2.x/2.2.5-hb.patch [new file with mode: 0644]
bacula/patches/2.2.x/2.2.5-lastwritten.patch [new file with mode: 0644]
bacula/patches/2.2.x/2.2.5-nextvol.patch [new file with mode: 0644]
bacula/patches/2.2.x/2.2.5-postgresql-errors.patch [new file with mode: 0644]
bacula/patches/2.2.x/2.2.5-tray-monitor.patch [new file with mode: 0644]
bacula/patches/2.2.x/2.2.5-verify-loop.patch [new file with mode: 0644]
bacula/src/dird/next_vol.c
bacula/technotes-2.1

diff --git a/bacula/patches/2.2.4-ansi-label.patch b/bacula/patches/2.2.4-ansi-label.patch
deleted file mode 100644 (file)
index d68e618..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
- This patch fixes bug #954.
- WEOF on non-appendable error when trying to label a tape with ANSI labels turned on.
-
- Apply it to version 2.2.4 (possibly earlier versions with):
-
- cd <bacula-source>
- patch -p0 <2.2.4-verify.patch
- ./configure (your options)
- make
- ...
- make install
-
-Index: block.c
-===================================================================
---- src/stored/block.c (revision 5615)
-+++ src/stored/block.c (revision 5615)
-@@ -273,6 +273,7 @@
-       dev->dev_errno = EIO;
-       Mmsg4(dev->errmsg, _("Volume data error at %u:%u! Wanted ID: \"%s\", got \"%s\". Buffer discarded.\n"),
-           dev->file, dev->block_num, BLKHDR2_ID, Id);
-+      Dmsg1(50, "%s", dev->errmsg);
-       if (block->read_errors == 0 || verbose >= 2) {
-          Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
-       }
-@@ -1008,8 +1009,19 @@
-       dev->set_ateof();
-       return false;             /* return eof */
-    }
-+
-    /* Continue here for successful read */
-+
-    block->read_len = stat;      /* save length read */
-+   if (dev->at_eof() && block->read_len == 80 && 
-+        (dcr->VolCatInfo.LabelType != B_BACULA_LABEL ||
-+         dcr->device->label_type != B_BACULA_LABEL)) {
-+      /* ***FIXME*** should check label */
-+      Dmsg2(100, "Ignore 80 byte ANSI label at %u:%u\n", dev->file, dev->block_num);
-+      dev->clear_eof();
-+      goto reread;             /* skip ANSI/IBM label */
-+   }
-+                                          
-    if (block->read_len < BLKHDR2_LENGTH) {
-       dev->dev_errno = EIO;
-       Mmsg4(dev->errmsg, _("Volume data error at %u:%u! Very short block of %d bytes on device %s discarded.\n"),
-
-Index: label.c
-===================================================================
---- src/stored/label.c (revision 5602)
-+++ src/stored/label.c (working copy)
-@@ -119,7 +119,6 @@
-    bstrncpy(dev->VolHdr.Id, "**error**", sizeof(dev->VolHdr.Id));
-   /* Read ANSI/IBM label if so requested */
--  
-   want_ansi_label = dcr->VolCatInfo.LabelType != B_BACULA_LABEL ||
-                     dcr->device->label_type != B_BACULA_LABEL;
-   if (want_ansi_label || dev->has_cap(CAP_CHECKLABELS)) {
-@@ -344,6 +343,9 @@
-       }
-    }
-+   /* Temporarily mark in append state to enable writing */
-+   dev->set_append();
-+
-    /* Create PRE_LABEL or VOL_LABEL if DVD */
-    create_volume_label(dev, VolName, PoolName, dvdnow);
-@@ -364,8 +366,6 @@
-    create_volume_label_record(dcr, dcr->rec);
-    dcr->rec->Stream = 0;
--   /* Temporarily mark in append state to enable writing */
--   dev->set_append();
-    if (!write_record_to_block(dcr->block, dcr->rec)) {
-       Dmsg2(130, "Bad Label write on %s: ERR=%s\n", dev->print_name(), dev->print_errmsg());
-       goto bail_out;
diff --git a/bacula/patches/2.2.4-lost-block.patch b/bacula/patches/2.2.4-lost-block.patch
deleted file mode 100644 (file)
index fbf7122..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-
- This patch fixes a race condition where a Job is terminating at the same
- time that another job reaches the end of Volume. In that case, sometimes
- the last block or two are not written to the Volume.  This seems to be 
- relatively rare, but does result in data loss.  This fixes bug #964.
-
- Apply the patch to Bacula version 2.2.4 (or possibly any previous 2.2.x 
- version) with:
-
- cd <bacula-source>
- patch -p0 <2.2.4-lost-block.patch
- ./configure (your options)
- make
- ...
- make install
-
-
-Index: src/stored/append.c
-===================================================================
---- src/stored/append.c        (revision 5602)
-+++ src/stored/append.c        (working copy)
-@@ -287,7 +287,7 @@
-     * Check if we can still write. This may not be the case
-     *  if we are at the end of the tape or we got a fatal I/O error.
-     */
--   if (dev->can_write()) {
-+   if (ok || dev->can_write()) {
-       if (!write_session_label(dcr, EOS_LABEL)) {
-          Jmsg1(jcr, M_FATAL, 0, _("Error writting end session label. ERR=%s\n"),
-                dev->bstrerror());
diff --git a/bacula/patches/2.2.4-parse-command.patch b/bacula/patches/2.2.4-parse-command.patch
deleted file mode 100644 (file)
index 312dd29..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-
- This patch resolves a command parser issue 
- causing a director segfault when using something
- like "run job 1 2"
-
- Apply to version 2.2.4 (and perhaps older 2.2.x versions) with
-
- cd <bacula-source>
- patch -p0 <2.2.4-parse-command.patch
- ./configure (your options)
- make
- ...
- make install
-
-
-Index: src/dird/ua_run.c
-===================================================================
---- src/dird/ua_run.c  (révision 5616)
-+++ src/dird/ua_run.c  (copie de travail)
-@@ -933,7 +933,7 @@
-             /* Note, yes and run have no value, so do not fail */
-             if (!ua->argv[i] && j != YES_POS /*yes*/) {
-                ua->send_msg(_("Value missing for keyword %s\n"), ua->argk[i]);
--               return true;
-+               return false;
-             }
-             Dmsg1(800, "Got keyword=%s\n", NPRT(kw[j]));
-             switch (j) {
diff --git a/bacula/patches/2.2.4-poll-mount.patch b/bacula/patches/2.2.4-poll-mount.patch
deleted file mode 100644 (file)
index a4676e9..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-
- This patch resolves bug #908 where a tape is not properly mounted
- (recognized) during a poll.
-
- Apply to version 2.2.4 (and perhaps older 2.2.x versions) with
-  
- cd <bacula-source>
- patch -p0 <2.2.4-poll-mount.patch
- ./configure (your options)
- make
- ...
- make install
-
-Index: src/stored/dev.c
-===================================================================
---- src/stored/dev.c   (revision 5553)
-+++ src/stored/dev.c   (working copy)
-@@ -1844,7 +1844,8 @@
-    /* Clean up device packet so it can be reused */
-    clear_opened();
--   state &= ~(ST_LABEL|ST_READ|ST_APPEND|ST_EOT|ST_WEOT|ST_EOF);
-+   state &= ~(ST_LABEL|ST_READ|ST_APPEND|ST_EOT|ST_WEOT|ST_EOF|
-+              ST_MOUNTED|ST_MEDIA|ST_SHORT|ST_FREESPACE_OK|ST_PART_SPOOLED);
-    label_type = B_BACULA_LABEL;
-    file = block_num = 0;
-    file_size = 0;
diff --git a/bacula/patches/2.2.4-replace.patch b/bacula/patches/2.2.4-replace.patch
deleted file mode 100644 (file)
index 58e4e51..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-
- This patch resolves bug #969 where the user can't change the
- replace option in the restore menu
-
- Apply to version 2.2.4 (and perhaps older 2.2.x versions) with
-
- cd <bacula-source>
- patch -p0 <2.2.4-replace.patch
- ./configure (your options)
- make
- ...
- make install
-
---- src/dird/ua_run.c   (révision 5721)
-+++ src/dird/ua_run.c   (copie de travail)
-@@ -424,6 +424,7 @@
-          }
-          opt = do_prompt(ua, "", _("Select replace option"), NULL, 0);
-          if (opt >=  0) {
-+            rc.replace = ReplaceOptions[opt].name;
-             jcr->replace = ReplaceOptions[opt].token;
-          }
-          goto try_again;
-
diff --git a/bacula/patches/2.2.4-restore.patch b/bacula/patches/2.2.4-restore.patch
deleted file mode 100644 (file)
index 3ef991e..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-
- This patch resolves bug #955 where the director segfault when
- where= option isn't specified anywhere.
-
- Apply to version 2.2.4 (and perhaps older 2.2.x versions) with
-
- cd <bacula-source>
- patch -p0 <2.2.4-restore.patch
- ./configure (your options)
- make
- ...
- make install
-
-
-Index: src/dird/restore.c
-===================================================================
---- src/dird/restore.c (revision 5601)
-+++ src/dird/restore.c (working copy)
-@@ -173,7 +173,7 @@
-    }
-    /* Send restore command */
--   char replace, *where, *cmd=NULL;
-+   char replace, *where, *cmd;
-    char empty = '\0';
-    if (jcr->replace != 0) {
-@@ -183,8 +183,6 @@
-    } else {
-       replace = REPLACE_ALWAYS;       /* always replace */
-    }
--   
--   where = &empty;                    /* default */
-    if (jcr->RegexWhere) {
-       where = jcr->RegexWhere;             /* override */
-@@ -199,7 +197,11 @@
-    } else if (jcr->job->RestoreWhere) {
-       where = jcr->job->RestoreWhere; /* no override take from job */
-       cmd = restorecmd;
--   } 
-+
-+   } else {                         /* nothing was specified */
-+      where = &empty;               /* use default */
-+      cmd   = restorecmd;                  
-+   }
-    
-    jcr->prefix_links = jcr->job->PrefixLinks;
diff --git a/bacula/patches/2.2.4-sd-auth-fail.patch b/bacula/patches/2.2.4-sd-auth-fail.patch
deleted file mode 100644 (file)
index 2e506e7..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-
- This patch applies to Bacula version 2.2.4 (possibly earlier 2.2.x versions)
- and fixes a Storage daemon authentication problem with the FD.  This fixes
- bug #953.  The patch also adds a bit of additional debug code and significantly
- strengthens the SD session key.
-
- Apply it to 2.2.4 with:
-
-  cd <bacula-source>
-  patch -p0 <2.2.4-sd-auth-fail.patch
-  make
-  ...
-  make install
-
-
-Index: src/stored/job.c
-===================================================================
---- src/stored/job.c   (revision 5602)
-+++ src/stored/job.c   (working copy)
-@@ -73,6 +73,7 @@
- {
-    int JobId;
-    char auth_key[100];
-+   char seed[100];
-    BSOCK *dir = jcr->dir_bsock;
-    POOL_MEM job_name, client_name, job, fileset_name, fileset_md5;
-    int JobType, level, spool_attributes, no_attributes, spool_data;
-@@ -91,7 +92,7 @@
-               &write_part_after_job, &PreferMountedVols);
-    if (stat != 13) {
-       pm_strcpy(jcr->errmsg, dir->msg);
--      bnet_fsend(dir, BAD_job, stat, jcr->errmsg);
-+      dir->fsend(BAD_job, stat, jcr->errmsg);
-       Dmsg1(100, ">dird: %s", dir->msg);
-       set_jcr_job_status(jcr, JS_ErrorTerminated);
-       return false;
-@@ -134,9 +135,10 @@
-    /*
-     * Pass back an authorization key for the File daemon
-     */
--   make_session_key(auth_key, NULL, 1);
--   bnet_fsend(dir, OKjob, jcr->VolSessionId, jcr->VolSessionTime, auth_key);
--   Dmsg1(100, ">dird: %s", dir->msg);
-+   bsnprintf(seed, sizeof(seed), "%p%d", jcr, JobId);
-+   make_session_key(auth_key, seed, 1);
-+   dir->fsend(OKjob, jcr->VolSessionId, jcr->VolSessionTime, auth_key);
-+   Dmsg2(100, ">dird jid=%u: %s", (uint32_t)jcr->JobId, dir->msg);
-    jcr->sd_auth_key = bstrdup(auth_key);
-    memset(auth_key, 0, sizeof(auth_key));
-    generate_daemon_event(jcr, "JobStart");
-@@ -169,17 +171,18 @@
-    timeout.tv_nsec = tv.tv_usec * 1000;
-    timeout.tv_sec = tv.tv_sec + me->client_wait;
--   Dmsg2(100, "%s waiting %d sec for FD to contact SD\n", 
--        jcr->Job, (int)me->client_wait);
-+   Dmsg3(050, "%s waiting %d sec for FD to contact SD key=%s\n",
-+         jcr->Job, (int)me->client_wait, jcr->sd_auth_key);
-+
-    /*
-     * Wait for the File daemon to contact us to start the Job,
-     *  when he does, we will be released, unless the 30 minutes
-     *  expires.
-     */
-    P(mutex);
--   for ( ; !job_canceled(jcr); ) {
-+   while ( !jcr->authenticated && !job_canceled(jcr) ) {
-       errstat = pthread_cond_timedwait(&jcr->job_start_wait, &mutex, &timeout);
--      if (errstat == 0 || errstat == ETIMEDOUT) {
-+      if (errstat == ETIMEDOUT || errstat == EINVAL || errstat == EPERM) {
-          break;
-       }
-    }
-@@ -195,7 +198,7 @@
- }
- /*
-- * After receiving a connection (in job.c) if it is
-+ * After receiving a connection (in dircmd.c) if it is
-  *   from the File daemon, this routine is called.
-  */
- void handle_filed_connection(BSOCK *fd, char *job_name)
-@@ -204,8 +207,8 @@
-    bmicrosleep(0, 50000);             /* wait 50 millisecs */
-    if (!(jcr=get_jcr_by_full_name(job_name))) {
--      Jmsg1(NULL, M_FATAL, 0, _("Job name not found: %s\n"), job_name);
--      Dmsg1(100, "Job name not found: %s\n", job_name);
-+      Jmsg1(NULL, M_FATAL, 0, _("FD connect failed: Job name not found: %s\n"), job_name);
-+      Dmsg1(3, "**** Job \"%s\" not found", job_name);
-       return;
-    }
-@@ -216,7 +219,7 @@
-    if (jcr->authenticated) {
-       Jmsg2(jcr, M_FATAL, 0, _("Hey!!!! JobId %u Job %s already authenticated.\n"),
--         jcr->JobId, jcr->Job);
-+         (uint32_t)jcr->JobId, jcr->Job);
-       free_jcr(jcr);
-       return;
-    }
-@@ -229,7 +232,7 @@
-       Jmsg(jcr, M_FATAL, 0, _("Unable to authenticate File daemon\n"));
-    } else {
-       jcr->authenticated = true;
--      Dmsg1(110, "OK Authentication Job %s\n", jcr->Job);
-+      Dmsg2(110, "OK Authentication jid=%u Job %s\n", (uint32_t)jcr->JobId, jcr->Job);
-    }
-    if (!jcr->authenticated) {
-@@ -274,9 +277,9 @@
-             }  
-             ok = dir_update_device(jcr, device->dev);
-             if (ok) {
--               ok = bnet_fsend(dir, OK_query);
-+               ok = dir->fsend(OK_query);
-             } else {
--               bnet_fsend(dir, NO_query);
-+               dir->fsend(NO_query);
-             }
-             return ok;
-          }
-@@ -289,9 +292,9 @@
-             }
-             ok = dir_update_changer(jcr, changer);
-             if (ok) {
--               ok = bnet_fsend(dir, OK_query);
-+               ok = dir->fsend(OK_query);
-             } else {
--               bnet_fsend(dir, NO_query);
-+               dir->fsend(NO_query);
-             }
-             return ok;
-          }
-@@ -299,12 +302,12 @@
-       /* If we get here, the device/autochanger was not found */
-       unbash_spaces(dir->msg);
-       pm_strcpy(jcr->errmsg, dir->msg);
--      bnet_fsend(dir, NO_device, dev_name.c_str());
-+      dir->fsend(NO_device, dev_name.c_str());
-       Dmsg1(100, ">dird: %s\n", dir->msg);
-    } else {
-       unbash_spaces(dir->msg);
-       pm_strcpy(jcr->errmsg, dir->msg);
--      bnet_fsend(dir, BAD_query, jcr->errmsg);
-+      dir->fsend(BAD_query, jcr->errmsg);
-       Dmsg1(100, ">dird: %s\n", dir->msg);
-    }
-@@ -322,7 +325,7 @@
- {
-    Dmsg1(900, "stored_free_jcr JobId=%u\n", jcr->JobId);
-    if (jcr->file_bsock) {
--      bnet_close(jcr->file_bsock);
-+      jcr->file_bsock->close();
-       jcr->file_bsock = NULL;
-    }
-    if (jcr->job_name) {
diff --git a/bacula/patches/2.2.4-sql.patch b/bacula/patches/2.2.4-sql.patch
deleted file mode 100644 (file)
index 24de099..0000000
+++ /dev/null
@@ -1,476 +0,0 @@
-
- This patch fixes several problems: it fixes incorrect or incomplete error
- messages; it fixes a problem opening the SQLite3 database when multiple
- simultaneous jobs were running; it fixes a bug with certain versions of
- MySQL where batch inserts failed because of table name character case
- (upper/lower) differences.
-
- It can be applied to version 2.2.4 (and possibly earlier 2.2.x versions)
- with:
-
-   cd <bacula-source>     
-   patch -p0 <2.2.4-sql.patch
-   ./configure (your options)
-   make
-   ...
-   make install
-
-
-           
-Index: src/cats/sql.c
-===================================================================
---- src/cats/sql.c     (revision 5687)
-+++ src/cats/sql.c     (working copy)
-@@ -115,7 +115,6 @@
-    bacula_db_version = 0;
-    if (!db_sql_query(mdb, query, int_handler, (void *)&bacula_db_version)) {
--      Mmsg(mdb->errmsg, "Database not created or server not running.\n");
-       Jmsg(jcr, M_FATAL, 0, "%s", mdb->errmsg);
-       return false;
-    }
-Index: src/cats/sqlite.c
-===================================================================
---- src/cats/sqlite.c  (revision 5687)
-+++ src/cats/sqlite.c  (working copy)
-@@ -148,6 +148,7 @@
-    int len;
-    struct stat statbuf;
-    int errstat;
-+   int retry = 0;
-    P(mutex);
-    if (mdb->connected) {
-@@ -157,8 +158,9 @@
-    mdb->connected = FALSE;
-    if ((errstat=rwl_init(&mdb->lock)) != 0) {
-+      berrno be;
-       Mmsg1(&mdb->errmsg, _("Unable to initialize DB lock. ERR=%s\n"),
--            strerror(errstat));
-+            be.bstrerror(errstat));
-       V(mutex);
-       return 0;
-    }
-@@ -178,28 +180,28 @@
-       return 0;
-    }
-+   for (mdb->db=NULL; !mdb->db && retry++ < 10; ) {
- #ifdef HAVE_SQLITE3
--   int stat = sqlite3_open(db_name, &mdb->db);
--   if (stat != SQLITE_OK) {
--      mdb->sqlite_errmsg = (char *)sqlite3_errmsg(mdb->db); 
--      sqlite3_close(mdb->db);
--      mdb->db = NULL;
--   } else {
--      mdb->sqlite_errmsg = NULL;
--   }
--#ifdef SQLITE3_INIT_QUERY
--   db_sql_query(mdb, SQLITE3_INIT_QUERY, NULL, NULL);
--#endif
--
-+      int stat = sqlite3_open(db_name, &mdb->db);
-+      if (stat != SQLITE_OK) {
-+         mdb->sqlite_errmsg = (char *)sqlite3_errmsg(mdb->db); 
-+         sqlite3_close(mdb->db);
-+         mdb->db = NULL;
-+      } else {
-+         mdb->sqlite_errmsg = NULL;
-+      }
- #else
--   mdb->db = sqlite_open(
--        db_name,                      /* database name */
--        644,                          /* mode */
--        &mdb->sqlite_errmsg);         /* error message */
-+      mdb->db = sqlite_open(
-+           db_name,                      /* database name */
-+           644,                          /* mode */
-+           &mdb->sqlite_errmsg);         /* error message */
- #endif
--   Dmsg0(300, "sqlite_open\n");
--
-+      Dmsg0(300, "sqlite_open\n");
-+      if (!mdb->db) {
-+         bmicrosleep(1, 0);
-+      }
-+   }
-    if (mdb->db == NULL) {
-       Mmsg2(&mdb->errmsg, _("Unable to open Database=%s. ERR=%s\n"),
-          db_name, mdb->sqlite_errmsg ? mdb->sqlite_errmsg : _("unknown"));
-@@ -209,10 +211,6 @@
-    }       
-    mdb->connected = true;
-    free(db_name);
--   if (!check_tables_version(jcr, mdb)) {
--      V(mutex);
--      return 0;
--   }
-    /* set busy handler to wait when we use mult_db_connections = 1 */
- #ifdef HAVE_SQLITE3
-@@ -221,6 +219,16 @@
-    sqlite_busy_handler(mdb->db, my_busy_handler, NULL);
- #endif
-+#if  defined(HAVE_SQLITE3) && defined(SQLITE3_INIT_QUERY)
-+   db_sql_query(mdb, SQLITE3_INIT_QUERY, NULL, NULL);
-+#endif
-+
-+   if (!check_tables_version(jcr, mdb)) {
-+      V(mutex);
-+      return 0;
-+   }
-+
-+
-    V(mutex);
-    return 1;
- }
-@@ -448,16 +456,20 @@
-    return mdb->fields[mdb->field++];
- }
--char *my_sqlite_batch_lock_query = "BEGIN";
--char *my_sqlite_batch_unlock_query = "COMMIT";
--char *my_sqlite_batch_fill_path_query = "INSERT INTO Path (Path)          " 
--                                        " SELECT DISTINCT Path FROM batch "
--                                        " EXCEPT SELECT Path FROM Path    ";
-+#ifdef HAVE_BATCH_FILE_INSERT
-+const char *my_sqlite_batch_lock_query = "BEGIN";
-+const char *my_sqlite_batch_unlock_query = "COMMIT";
--char *my_sqlite_batch_fill_filename_query = "INSERT INTO Filename (Name)       " 
--                                            " SELECT DISTINCT Name FROM batch  "
--                                            " EXCEPT SELECT Name FROM Filename ";
-+const char *my_sqlite_batch_fill_path_query = 
-+   "INSERT INTO Path (Path)" 
-+   " SELECT DISTINCT Path FROM batch"
-+   " EXCEPT SELECT Path FROM Path";
-+const char *my_sqlite_batch_fill_filename_query = 
-+   "INSERT INTO Filename (Name)"
-+   " SELECT DISTINCT Name FROM batch "
-+   " EXCEPT SELECT Name FROM Filename";
-+#endif /* HAVE_BATCH_FILE_INSERT */
- #endif /* HAVE_SQLITE */
-Index: src/cats/cats.h
-===================================================================
---- src/cats/cats.h    (revision 5687)
-+++ src/cats/cats.h    (working copy)
-@@ -187,10 +187,10 @@
- int        my_sqlite_query(B_DB *mdb, const char *cmd);
- void       my_sqlite_field_seek(B_DB *mdb, int field);
- SQL_FIELD *my_sqlite_fetch_field(B_DB *mdb);
--extern char* my_sqlite_batch_lock_query;
--extern char* my_sqlite_batch_unlock_query;
--extern char* my_sqlite_batch_fill_filename_query;
--extern char* my_sqlite_batch_fill_path_query;
-+extern const char* my_sqlite_batch_lock_query;
-+extern const char* my_sqlite_batch_unlock_query;
-+extern const char* my_sqlite_batch_fill_filename_query;
-+extern const char* my_sqlite_batch_fill_path_query;
- #else
-@@ -317,10 +317,10 @@
- int        my_sqlite_query(B_DB *mdb, const char *cmd);
- void       my_sqlite_field_seek(B_DB *mdb, int field);
- SQL_FIELD *my_sqlite_fetch_field(B_DB *mdb);
--extern char* my_sqlite_batch_lock_query;
--extern char* my_sqlite_batch_unlock_query;
--extern char* my_sqlite_batch_fill_filename_query;
--extern char* my_sqlite_batch_fill_path_query;
-+extern const char* my_sqlite_batch_lock_query;
-+extern const char* my_sqlite_batch_unlock_query;
-+extern const char* my_sqlite_batch_fill_filename_query;
-+extern const char* my_sqlite_batch_fill_path_query;
- #else
-@@ -398,11 +398,11 @@
- #define sql_batch_fill_path_query       my_mysql_batch_fill_path_query
--extern char* my_mysql_batch_lock_path_query;
--extern char* my_mysql_batch_lock_filename_query;
--extern char* my_mysql_batch_unlock_tables_query;
--extern char* my_mysql_batch_fill_filename_query;
--extern char* my_mysql_batch_fill_path_query;
-+extern const char* my_mysql_batch_lock_path_query;
-+extern const char* my_mysql_batch_lock_filename_query;
-+extern const char* my_mysql_batch_unlock_tables_query;
-+extern const char* my_mysql_batch_fill_filename_query;
-+extern const char* my_mysql_batch_fill_path_query;
- extern void  my_mysql_free_result(B_DB *mdb);
- #else
-@@ -486,11 +486,11 @@
- int my_postgresql_batch_insert(JCR *jcr, B_DB *mdb, ATTR_DBR *ar);
- char *my_postgresql_copy_escape(char *dest, char *src, size_t len);
--extern char* my_pg_batch_lock_path_query;
--extern char* my_pg_batch_lock_filename_query;
--extern char* my_pg_batch_unlock_tables_query;
--extern char* my_pg_batch_fill_filename_query;
--extern char* my_pg_batch_fill_path_query;
-+extern const char* my_pg_batch_lock_path_query;
-+extern const char* my_pg_batch_lock_filename_query;
-+extern const char* my_pg_batch_unlock_tables_query;
-+extern const char* my_pg_batch_fill_filename_query;
-+extern const char* my_pg_batch_fill_path_query;
- /* "Generic" names for easier conversion */
- #define sql_store_result(x)   ((x)->result)
-Index: src/cats/mysql.c
-===================================================================
---- src/cats/mysql.c   (revision 5687)
-+++ src/cats/mysql.c   (working copy)
-@@ -149,8 +149,9 @@
-    }
-    if ((errstat=rwl_init(&mdb->lock)) != 0) {
-+      berrno be;
-       Mmsg1(&mdb->errmsg, _("Unable to initialize DB lock. ERR=%s\n"),
--            strerror(errstat));
-+            be.bstrerror(errstat));
-       V(mutex);
-       return 0;
-    }
-@@ -403,33 +404,27 @@
-    db_unlock(mdb);
- }
--char *my_mysql_batch_lock_path_query = "LOCK TABLES Path write,     " 
--                                       "            batch write,    " 
--                                       "            Path as p write ";
-+#ifdef HAVE_BATCH_FILE_INSERT
-+const char *my_mysql_batch_lock_path_query = 
-+   "LOCK TABLES Path write, batch write, Path as p write";
--char *my_mysql_batch_lock_filename_query = "LOCK TABLES Filename write,     "
--                                           "            batch write,        "
--                                           "            Filename as f write ";
-+const char *my_mysql_batch_lock_filename_query = 
-+   "LOCK TABLES Filename write, batch write, Filename as f write";
--char *my_mysql_batch_unlock_tables_query = "UNLOCK TABLES";
-+const char *my_mysql_batch_unlock_tables_query = "UNLOCK TABLES";
--char *my_mysql_batch_fill_path_query = "INSERT INTO Path (Path)        "
--                                       " SELECT a.Path FROM            " 
--                                       "  (SELECT DISTINCT Path        "
--                                       "     FROM batch) AS a          " 
--                                       " WHERE NOT EXISTS              "
--                                       "  (SELECT Path                 "
--                                       "     FROM Path AS p            "
--                                       "    WHERE p.Path = a.Path)     ";     
-+const char *my_mysql_batch_fill_path_query = 
-+   "INSERT INTO Path (Path) "
-+    "SELECT a.Path FROM " 
-+     "(SELECT DISTINCT Path FROM batch) AS a WHERE NOT EXISTS "
-+     "(SELECT Path FROM Path AS p WHERE p.Path = a.Path)";     
--char *my_mysql_batch_fill_filename_query = "INSERT INTO Filename (Name)       "
--                                           "  SELECT a.Name FROM              " 
--                                           "   (SELECT DISTINCT Name          "
--                                           "      FROM batch) AS a            " 
--                                           "  WHERE NOT EXISTS                "
--                                           "   (SELECT Name                   "
--                                           "      FROM Filename AS f          "
--                                           "      WHERE f.Name = a.Name)      ";
-+const char *my_mysql_batch_fill_filename_query = 
-+   "INSERT INTO Filename (Name) "
-+    "SELECT a.Name FROM " 
-+     "(SELECT DISTINCT Name FROM batch) AS a WHERE NOT EXISTS "
-+     "(SELECT Name FROM Filename AS f WHERE f.Name = a.Name)";
-+#endif /* HAVE_BATCH_FILE_INSERT */
- #endif /* HAVE_MYSQL */
-Index: src/cats/sql_create.c
-===================================================================
---- src/cats/sql_create.c      (revision 5687)
-+++ src/cats/sql_create.c      (working copy)
-@@ -668,6 +668,8 @@
-  *  };
-  */
-+#ifdef HAVE_BATCH_FILE_INSERT
-+
- /*  All sql_batch_* functions are used to do bulk batch insert in File/Filename/Path
-  *  tables. This code can be activated by adding "#define HAVE_BATCH_FILE_INSERT 1"
-  *  in baconfig.h
-@@ -690,13 +692,13 @@
-    db_lock(mdb);
-    ok =  db_sql_query(mdb,
--             " CREATE TEMPORARY TABLE batch "
--             "        (fileindex integer,   "
--             "        jobid integer,        "
--             "        path blob,            "
--             "        name blob,            "
--             "        lstat tinyblob,       "
--             "        md5 tinyblob)         ",NULL, NULL);
-+             "CREATE TEMPORARY TABLE batch ("
-+                "FileIndex integer,"
-+                "JobId integer,"
-+                "Path blob,"
-+                "Name blob,"
-+                "LStat tinyblob,"
-+                "MD5 tinyblob)",NULL, NULL);
-    db_unlock(mdb);
-    return ok;
- }
-@@ -746,7 +748,6 @@
-    return true;
- }
--#ifdef HAVE_BATCH_FILE_INSERT
- /* 
-  * Returns 1 if OK
-  *         0 if failed
-@@ -794,7 +795,7 @@
-    
-    if (!db_sql_query(jcr->db_batch,sql_batch_fill_filename_query, NULL,NULL)) {
-       Jmsg(jcr,M_FATAL,0,"Can't fill Filename table %s\n",jcr->db_batch->errmsg);
--      QUERY_DB(jcr, jcr->db_batch, sql_batch_unlock_tables_query);
-+      db_sql_query(jcr->db_batch, sql_batch_unlock_tables_query, NULL, NULL);
-       return false;            
-    }
-@@ -804,12 +805,12 @@
-    }
-    
-    if (!db_sql_query(jcr->db_batch, 
--       " INSERT INTO File (FileIndex, JobId, PathId, FilenameId, LStat, MD5)"
--       "  SELECT batch.FileIndex, batch.JobId, Path.PathId,               " 
--       "         Filename.FilenameId,batch.LStat, batch.MD5               "
--       "  FROM batch                                                      "
--       "    JOIN Path ON (batch.Path = Path.Path)                         "
--       "    JOIN Filename ON (batch.Name = Filename.Name)                 ",
-+       "INSERT INTO File (FileIndex, JobId, PathId, FilenameId, LStat, MD5)"
-+         "SELECT batch.FileIndex, batch.JobId, Path.PathId, "
-+                "Filename.FilenameId,batch.LStat, batch.MD5 "
-+           "FROM batch "
-+           "JOIN Path ON (batch.Path = Path.Path) "
-+           "JOIN Filename ON (batch.Name = Filename.Name)",
-                      NULL,NULL))
-    {
-       Jmsg(jcr, M_FATAL, 0, "Can't fill File table %s\n", jcr->db_batch->errmsg);
-@@ -845,19 +846,24 @@
-                                       mdb->db_port,
-                                       mdb->db_socket,
-                                       1 /* multi_db = true */);
-+      if (!jcr->db_batch) {
-+         Mmsg1(&mdb->errmsg, _("Could not init batch database: \"%s\".\n"),
-+                        jcr->db->db_name);
-+         Jmsg1(jcr, M_FATAL, 0, "%s", mdb->errmsg);
-+         return false;
-+      }
--      if (!jcr->db_batch || !db_open_database(jcr, jcr->db_batch)) {
--         Jmsg(jcr, M_FATAL, 0, _("Could not open database \"%s\".\n"),
--              jcr->db->db_name);
--         if (jcr->db_batch) {
--            Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db_batch));
--         }
-+      if (!db_open_database(jcr, jcr->db_batch)) {
-+         Mmsg2(&mdb->errmsg,  _("Could not open database \"%s\": ERR=%s\n"),
-+              jcr->db->db_name, db_strerror(jcr->db_batch));
-+         Jmsg1(jcr, M_FATAL, 0, "%s", mdb->errmsg);
-          return false;
-       }      
-       
-       if (!sql_batch_start(jcr, jcr->db_batch)) {
--         Jmsg(jcr, M_FATAL, 0, 
--              "Can't start batch mode %s", db_strerror(jcr->db_batch));
-+         Mmsg1(&mdb->errmsg, 
-+              "Can't start batch mode: ERR=%s", db_strerror(jcr->db_batch));
-+         Jmsg1(jcr, M_FATAL, 0, "%s", mdb->errmsg);
-          return false;
-       }
-       Dmsg3(100, "initdb ref=%d connected=%d db=%p\n", jcr->db_batch->ref_count,
-@@ -870,10 +876,10 @@
-     */
-    if (!(ar->Stream == STREAM_UNIX_ATTRIBUTES ||
-          ar->Stream == STREAM_UNIX_ATTRIBUTES_EX)) {
--      Mmsg1(&bdb->errmsg, _("Attempt to put non-attributes into catalog. Stream=%d\n"),
-+      Mmsg1(&mdb->errmsg, _("Attempt to put non-attributes into catalog. Stream=%d\n"),
-          ar->Stream);
--      Jmsg(jcr, M_ERROR, 0, "%s", bdb->errmsg);
--      return 0;
-+      Jmsg(jcr, M_FATAL, 0, "%s", mdb->errmsg);
-+      return false;
-    }
-    split_path_and_file(jcr, bdb, ar->fname);
-Index: src/cats/postgresql.c
-===================================================================
---- src/cats/postgresql.c      (revision 5687)
-+++ src/cats/postgresql.c      (working copy)
-@@ -605,13 +605,13 @@
-    Dmsg0(500, "my_postgresql_batch_start started\n");
-    if (my_postgresql_query(mdb,
--                           " CREATE TEMPORARY TABLE batch "
--                           "        (fileindex int,       "
--                           "        jobid int,            "
--                           "        path varchar,         "
--                           "        name varchar,         "
--                           "        lstat varchar,        "
--                           "        md5 varchar)") == 1)
-+                           "CREATE TEMPORARY TABLE batch ("
-+                               "fileindex int,"
-+                               "jobid int,"
-+                               "path varchar,"
-+                               "name varchar,"
-+                               "lstat varchar,"
-+                               "md5 varchar)") == 1)
-    {
-       Dmsg0(500, "my_postgresql_batch_start failed\n");
-       return 1;
-@@ -785,22 +785,29 @@
-    return dest;
- }
--char *my_pg_batch_lock_path_query = "BEGIN; LOCK TABLE Path IN SHARE ROW EXCLUSIVE MODE";
-+#ifdef HAVE_BATCH_FILE_INSERT
-+const char *my_pg_batch_lock_path_query = 
-+   "BEGIN; LOCK TABLE Path IN SHARE ROW EXCLUSIVE MODE";
--char *my_pg_batch_lock_filename_query = "BEGIN; LOCK TABLE Filename IN SHARE ROW EXCLUSIVE MODE";
-+const char *my_pg_batch_lock_filename_query = 
-+   "BEGIN; LOCK TABLE Filename IN SHARE ROW EXCLUSIVE MODE";
--char *my_pg_batch_unlock_tables_query = "COMMIT";
-+const char *my_pg_batch_unlock_tables_query = "COMMIT";
--char *my_pg_batch_fill_path_query = "INSERT INTO Path (Path)                                    "
--                                    "  SELECT a.Path FROM                                       "
--                                    "      (SELECT DISTINCT Path FROM batch) AS a               "
--                                    "  WHERE NOT EXISTS (SELECT Path FROM Path WHERE Path = a.Path) ";
-+const char *my_pg_batch_fill_path_query = 
-+   "INSERT INTO Path (Path) "
-+    "SELECT a.Path FROM "
-+     "(SELECT DISTINCT Path FROM batch) AS a "
-+      "WHERE NOT EXISTS (SELECT Path FROM Path WHERE Path = a.Path) ";
--char *my_pg_batch_fill_filename_query = "INSERT INTO Filename (Name)        "
--                                        "  SELECT a.Name FROM               "
--                                        "    (SELECT DISTINCT Name FROM batch) as a "
--                                        "    WHERE NOT EXISTS               "
--                                        "      (SELECT Name FROM Filename WHERE Name = a.Name)";
-+const char *my_pg_batch_fill_filename_query = 
-+   "INSERT INTO Filename (Name) "
-+    "SELECT a.Name FROM "
-+     "(SELECT DISTINCT Name FROM batch) as a "
-+      "WHERE NOT EXISTS "
-+       "(SELECT Name FROM Filename WHERE Name = a.Name)";
-+#endif /* HAVE_BATCH_FILE_INSERT */
-+
- #endif /* HAVE_POSTGRESQL */
diff --git a/bacula/patches/2.2.4-verify.patch b/bacula/patches/2.2.4-verify.patch
deleted file mode 100644 (file)
index 21e9af3..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
- This patch fixes bug #958 A Verify catalog Job that has differences reports Verify OK.
-
- Apply it to version 2.2.4 (possibly earlier versions with):
-
- cd <bacula-source>
- patch -p0 <2.2.4-verify.patch
- ./configure (your options)
- make
- ...
- make install
-
-Index: src/dird/verify.c
-===================================================================
---- src/dird/verify.c  (revision 5553)
-+++ src/dird/verify.c  (working copy)
-@@ -332,13 +332,10 @@
-    }
-    stat = wait_for_job_termination(jcr);
--   if (stat == JS_Terminated) {
--      verify_cleanup(jcr, stat);
--      return true;
--   }
-+   verify_cleanup(jcr, stat);
-+   return true;
- bail_out:
--   verify_cleanup(jcr, JS_ErrorTerminated);
-    return false;
- }
-@@ -421,7 +418,7 @@
-    jobstatus_to_ascii(jcr->FDJobStatus, fd_term_msg, sizeof(fd_term_msg));
-    if (jcr->JobLevel == L_VERIFY_VOLUME_TO_CATALOG) {
-       jobstatus_to_ascii(jcr->SDJobStatus, sd_term_msg, sizeof(sd_term_msg));
--   Jmsg(jcr, msg_type, 0, _("Bacula %s %s (%s): %s\n"
-+      Jmsg(jcr, msg_type, 0, _("Bacula %s %s (%s): %s\n"
- "  Build OS:               %s %s %s\n"
- "  JobId:                  %d\n"
- "  Job:                    %s\n"
-@@ -456,7 +453,7 @@
-          sd_term_msg,
-          term_msg);
-    } else {
--   Jmsg(jcr, msg_type, 0, _("Bacula %s %s (%s): %s\n"
-+      Jmsg(jcr, msg_type, 0, _("Bacula %s %s (%s): %s\n"
- "  Build:                  %s %s %s\n"
- "  JobId:                  %d\n"
- "  Job:                    %s\n"
-@@ -750,7 +747,9 @@
-       stat = JS_Differences;
-    }
-    free_pool_memory(fname);
--   set_jcr_job_status(jcr, stat);
-+   if (!job_canceled(jcr)) {
-+      jcr->JobStatus = stat;
-+   }
-    return stat == JS_Terminated;
- }
-Index: src/lib/jcr.c
-===================================================================
---- src/lib/jcr.c      (revision 5553)
-+++ src/lib/jcr.c      (working copy)
-@@ -614,9 +614,8 @@
-          /* Override more minor status */
-          jcr->JobStatus = JobStatus;
-          break;
--      default:
--         break;
-       }
-+      break;
-    default:
-       jcr->JobStatus = JobStatus;
-    }
diff --git a/bacula/patches/2.2.5-deamon.patch b/bacula/patches/2.2.5-deamon.patch
deleted file mode 100644 (file)
index 6e82f1e..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-
- This patch fixes the default behavior of a non-DEVELOPER version of Bacula
- to close STDIN, STDOUT, and STDERR so that an ssh that starts bacula
- will not hang.  It also fixes a crash in bat when bat is executed and
- cannot connect to the Director (e.g. it is not running).
- This patch fixes bugs #991 and #993.
-
- Apply this fix to Bacula version 2.2.5 with:
-
- cd <bacula-source>
- patch -p0 <2.2.5-daemon.patch
- ./configure (your options)
- make
- ...
- make install
-
-
-Index: src/lib/message.c
-===================================================================
---- src/lib/message.c  (revision 5744)
-+++ src/lib/message.c  (working copy)
-@@ -52,7 +52,8 @@
-  */
- const char *working_directory = NULL;       /* working directory path stored here */
- int verbose = 0;                      /* increase User messages */
--int debug_level = 1;                  /* debug level */
-+/* Keep debug level set to zero by default */
-+int debug_level = 0;                  /* debug level */
- time_t daemon_start_time = 0;         /* Daemon start time */
- const char *version = VERSION " (" BDATE ")";
- char my_name[30];                     /* daemon name is stored here */
-@@ -1338,7 +1339,7 @@
-       jcr = get_jcr_from_tsd();
-    }
-    /* If no jcr or dequeuing send to daemon to avoid recursion */
--   if (!jcr || jcr->dequeuing) {
-+   if ((jcr && !jcr->msg_queue) || !jcr || jcr->dequeuing) {
-       /* jcr==NULL => daemon message, safe to send now */
-       Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
-       free(item);
diff --git a/bacula/patches/2.2.5-hb.patch b/bacula/patches/2.2.5-hb.patch
deleted file mode 100644 (file)
index b8d81c8..0000000
+++ /dev/null
@@ -1,186 +0,0 @@
-
- This patch fixes bug #947 where a large number of emails were generated
- because the heartbeat interval was small and the tape in the drive did
- not correspond to the one wanted by Bacula.
-
- Apply the patch to version 2.2.5 (and probably any 2.2.x version) with:
-
- cd <bacula-source>
- ./configure <your options>
- patch -p0 <2.2.5-hb.patch
- make
- ...
- make install
-
-
-Index: src/stored/wait.c
-===================================================================
---- src/stored/wait.c  (revision 5814)
-+++ src/stored/wait.c  (working copy)
-@@ -40,9 +40,8 @@
- #include "bacula.h"                   /* pull in global headers */
- #include "stored.h"                   /* pull in Storage Deamon headers */
--//static bool double_jcr_wait_time(JCR *jcr);
-+const int dbglvl = 400;
--
- /*
-  * Wait for SysOp to mount a tape on a specific device
-  *
-@@ -62,7 +61,7 @@
-    JCR *jcr = dcr->jcr;
-    dev->dlock();  
--   Dmsg1(100, "Enter blocked=%s\n", dev->print_blocked());
-+   Dmsg1(dbglvl, "Enter blocked=%s\n", dev->print_blocked());
-    unmounted = is_device_unmounted(dev);
-    dev->poll = false;
-@@ -84,27 +83,28 @@
-    }
-    if (!unmounted) {
--      Dmsg1(400, "blocked=%s\n", dev->print_blocked());
-+      Dmsg1(dbglvl, "blocked=%s\n", dev->print_blocked());
-       dev->dev_prev_blocked = dev->blocked();
-       dev->set_blocked(BST_WAITING_FOR_SYSOP); /* indicate waiting for mount */
-    }
-    for ( ; !job_canceled(jcr); ) {
--      time_t now, start;
-+      time_t now, start, total_waited;
-       gettimeofday(&tv, &tz);
-       timeout.tv_nsec = tv.tv_usec * 1000;
-       timeout.tv_sec = tv.tv_sec + add_wait;
--      Dmsg4(400, "I'm going to sleep on device %s. HB=%d wait=%d add_wait=%d\n", 
--         dev->print_name(), (int)me->heartbeat_interval, dev->wait_sec, add_wait);
-+      Dmsg4(dbglvl, "I'm going to sleep on device %s. HB=%d rem_wait=%d add_wait=%d\n", 
-+         dev->print_name(), (int)me->heartbeat_interval, dev->rem_wait_sec, add_wait);
-       start = time(NULL);
-       /* Wait required time */
-       stat = pthread_cond_timedwait(&dev->wait_next_vol, &dev->m_mutex, &timeout);
--      Dmsg2(400, "Wokeup from sleep on device stat=%d blocked=%s\n", stat,
-+      Dmsg2(dbglvl, "Wokeup from sleep on device stat=%d blocked=%s\n", stat,
-          dev->print_blocked());
-       now = time(NULL);
-+      total_waited = now - first_start;
-       dev->rem_wait_sec -= (now - start);
-       /* Note, this always triggers the first time. We want that. */
-@@ -113,7 +113,7 @@
-             /* send heartbeats */
-             if (jcr->file_bsock) {
-                jcr->file_bsock->signal(BNET_HEARTBEAT);
--               Dmsg0(400, "Send heartbeat to FD.\n");
-+               Dmsg0(dbglvl, "Send heartbeat to FD.\n");
-             }
-             if (jcr->dir_bsock) {
-                jcr->dir_bsock->signal(BNET_HEARTBEAT);
-@@ -131,7 +131,7 @@
-       if (dev->rem_wait_sec <= 0) {  /* on exceeding wait time return */
--         Dmsg0(400, "Exceed wait time.\n");
-+         Dmsg0(dbglvl, "Exceed wait time.\n");
-          stat = W_TIMEOUT;
-          break;
-       }
-@@ -142,8 +142,8 @@
-       unmounted = is_device_unmounted(dev);
-       if (!unmounted && dev->vol_poll_interval &&
--          (now - first_start >= dev->vol_poll_interval)) {
--         Dmsg1(400, "In wait blocked=%s\n", dev->print_blocked());
-+          (total_waited >= dev->vol_poll_interval)) {
-+         Dmsg1(dbglvl, "poll return in wait blocked=%s\n", dev->print_blocked());
-          dev->poll = true;            /* returning a poll event */
-          stat = W_POLL;
-          break;
-@@ -152,6 +152,7 @@
-        * Check if user mounted the device while we were waiting
-        */
-       if (dev->blocked() == BST_MOUNT) {   /* mount request ? */
-+         Dmsg0(dbglvl, "Mounted return.\n");
-          stat = W_MOUNT;
-          break;
-       }
-@@ -160,30 +161,39 @@
-        * If we did not timeout, then some event happened, so
-        *   return to check if state changed.   
-        */
--      if (stat != 0) {
-+      if (stat != ETIMEDOUT) {
-+         berrno be;
-+         Dmsg2(dbglvl, "Wake return. stat=%d. ERR=%s\n", stat, be.bstrerror(stat));
-          stat = W_WAKE;          /* someone woke us */
-          break;
-       }
-       /* 
-        * At this point, we know we woke up because of a timeout,
--       *   that was due to a heartbeat, so we just update
--       *   the wait counters and continue.
-+       *   that was due to a heartbeat, because any other reason would
-+       *   have caused us to return, so update the wait counters and continue.
-        */
--      add_wait = dev->wait_sec - (now - start);
-+      add_wait = dev->rem_wait_sec;
-+      if (me->heartbeat_interval && add_wait > me->heartbeat_interval) {
-+         add_wait = me->heartbeat_interval;
-+      }
-+      /* If the user did not unmount the tape and we are polling, ensure
-+       *  that we poll at the correct interval.
-+       */
-+      if (!unmounted && dev->vol_poll_interval && 
-+           add_wait > dev->vol_poll_interval - total_waited) {
-+         add_wait = dev->vol_poll_interval - total_waited;
-+      }
-       if (add_wait < 0) {
-          add_wait = 0;
-       }
--      if (me->heartbeat_interval && add_wait > me->heartbeat_interval) {
--         add_wait = me->heartbeat_interval;
--      }
-    }
-    if (!unmounted) {
-       dev->set_blocked(dev->dev_prev_blocked);    /* restore entry state */
--      Dmsg1(400, "set %s\n", dev->print_blocked());
-+      Dmsg1(dbglvl, "set %s\n", dev->print_blocked());
-    }
--   Dmsg1(400, "Exit blocked=%s\n", dev->print_blocked());
-+   Dmsg1(dbglvl, "Exit blocked=%s\n", dev->print_blocked());
-    dev->dunlock();
-    return stat;
- }
-@@ -209,7 +219,7 @@
-    const int max_wait_time = 1 * 60;       /* wait 1 minute */
-    char ed1[50];
--   Dmsg0(100, "Enter wait_for_device\n");
-+   Dmsg0(dbglvl, "Enter wait_for_device\n");
-    P(device_release_mutex);
-    if (++retries % 5 == 0) {
-@@ -222,14 +232,14 @@
-    timeout.tv_nsec = tv.tv_usec * 1000;
-    timeout.tv_sec = tv.tv_sec + max_wait_time;
--   Dmsg1(100, "JobId=%u going to wait for a device.\n", (uint32_t)jcr->JobId);
-+   Dmsg0(dbglvl, "Going to wait for a device.\n");
-    /* Wait required time */
-    stat = pthread_cond_timedwait(&wait_device_release, &device_release_mutex, &timeout);
--   Dmsg2(100, "JobId=%u wokeup from sleep on device stat=%d\n", (uint32_t)jcr->JobId, stat);
-+   Dmsg1(dbglvl, "Wokeup from sleep on device stat=%d\n", stat);
-    V(device_release_mutex);
--   Dmsg2(100, "JobId=%u return from wait_device ok=%d\n", (uint32_t)jcr->JobId, ok);
-+   Dmsg1(dbglvl, "Return from wait_device ok=%d\n", ok);
-    return ok;
- }
diff --git a/bacula/patches/2.2.5-lastwritten.patch b/bacula/patches/2.2.5-lastwritten.patch
deleted file mode 100644 (file)
index c5373bc..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-
-  This bug fixes the LastWritten field which was updated during
-  a restore (or a reading migration)
-  This fixes bug #982
-
-  This patch applies to Bacula version 2.2.5 (and previous versions),
-  and can be applied with the following:
-
-  cd <bacula-source>
-  patch -p0 <2.2.5-lastwritten.patch
-  ./configure (your options)
-  make
-  ...
-  make install
-
-
-
-Index: src/dird/catreq.c
-===================================================================
---- src/dird/catreq.c  (révision 5789)
-+++ src/dird/catreq.c  (copie de travail)
-@@ -266,6 +266,11 @@
-          }
-       }
-       Dmsg2(400, "Update media: BefVolJobs=%u After=%u\n", mr.VolJobs, sdmr.VolJobs);
-+      /* Check if the volume has been written by the job, 
-+       * and update the LastWritten field if needed */
-+      if (mr.VolBlocks != sdmr.VolBlocks) {
-+         mr.LastWritten = sdmr.LastWritten;
-+      }
-       /* Copy updated values to original media record */
-       mr.VolJobs      = sdmr.VolJobs;
-       mr.VolFiles     = sdmr.VolFiles;
-@@ -274,7 +279,6 @@
-       mr.VolMounts    = sdmr.VolMounts;
-       mr.VolErrors    = sdmr.VolErrors;
-       mr.VolWrites    = sdmr.VolWrites;
--      mr.LastWritten  = sdmr.LastWritten;
-       mr.Slot         = sdmr.Slot;
-       mr.InChanger    = sdmr.InChanger;
-       mr.VolReadTime  = sdmr.VolReadTime;
diff --git a/bacula/patches/2.2.5-nextvol.patch b/bacula/patches/2.2.5-nextvol.patch
deleted file mode 100644 (file)
index 27bf0d5..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-
-  This bug fixes the warning message that prints each time an automatic
-  Volume name is created.  This fixes bug #979
-
-  This patch applies to Bacula version 2.2.5 (not to previous versions),
-  and can be applied with the following:
-
-  cd <bacula-source>
-  patch -p0 <2.2.5-newvol.patch
-  ./configure (your options)
-  make
-  ...
-  make install
-
-
-
-Index: src/dird/newvol.c
-===================================================================
---- src/dird/newvol.c  (revision 5717)
-+++ src/dird/newvol.c  (working copy)
-@@ -124,7 +124,7 @@
-    mr->VolumeName[0] = 0;
-    bstrncpy(name, pr->LabelFormat, sizeof(name));
-    ctx.value = 0;
--   Mmsg(query, "SELECT MAX(MediaId) FROM Media,POOL WHERE Pool.PoolId=%s", 
-+   Mmsg(query, "SELECT MAX(MediaId) FROM Media,Pool WHERE Pool.PoolId=%s", 
-         edit_int64(pr->PoolId, ed1));
-    if (!db_sql_query(jcr->db, query.c_str(), db_int64_handler, (void *)&ctx)) {
-       Jmsg(jcr, M_WARNING, 0, _("SQL failed, but ignored. ERR=%s\n"), db_strerror(jcr->db));
diff --git a/bacula/patches/2.2.5-postgresql-errors.patch b/bacula/patches/2.2.5-postgresql-errors.patch
deleted file mode 100644 (file)
index fb52b80..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-  After a sql error, the error message that is printed 
-  is incorrect and does not include the postgresql error message.  
-  It fixes #989
-
-  This patch applies to Bacula version 2.2.5 (and previous versions),
-  and can be applied with the following:
-
-  cd <bacula-source>
-  patch -p0 <2.2.5-postgresql-errors.patch
-  ./configure (your options)
-  make
-  ...
-  make install
-
-
-Index: src/cats/cats.h
-===================================================================
---- src/cats/cats.h    (révision 5763)
-+++ src/cats/cats.h    (copie de travail)
-@@ -498,7 +498,7 @@
- #define sql_fetch_row(x)      my_postgresql_fetch_row(x)
- #define sql_query(x, y)       my_postgresql_query((x), (y))
- #define sql_close(x)          PQfinish((x)->db)
--#define sql_strerror(x)       PQresultErrorMessage((x)->result)
-+#define sql_strerror(x)       PQerrorMessage((x)->db)
- #define sql_num_rows(x)       ((unsigned) PQntuples((x)->result))
- #define sql_data_seek(x, i)   my_postgresql_data_seek((x), (i))
- #define sql_affected_rows(x)  ((unsigned) atoi(PQcmdTuples((x)->result)))
diff --git a/bacula/patches/2.2.5-tray-monitor.patch b/bacula/patches/2.2.5-tray-monitor.patch
deleted file mode 100644 (file)
index 542aea7..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-
- This patch activates the Close button in the tray monitor window.
- It fixes bug #986.
-
- Apply it to Bacula version 2.2.5 with:
-
- cd <bacula-source>
- patch -p0 <2.2.5-tray-monitor.patch
- make
- ...
- make install
-
-Index: src/tray-monitor/tray-monitor.c
-===================================================================
---- src/tray-monitor/tray-monitor.c    (revision 5717)
-+++ src/tray-monitor/tray-monitor.c    (working copy)
-@@ -478,7 +478,7 @@
-    gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, FALSE, 0);
-    button = new_image_button("gtk-close", _("Close"));
--// g_signal_connect_swapped(G_OBJECT(button), "clicked", G_CALLBACK(gtk_widget_hide), G_OBJECT(window));
-+   g_signal_connect_swapped(G_OBJECT(button), "clicked", G_CALLBACK(gtk_widget_hide), G_OBJECT(window));
-    gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, FALSE, 0);
-    gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
diff --git a/bacula/patches/2.2.5-verify-loop.patch b/bacula/patches/2.2.5-verify-loop.patch
deleted file mode 100644 (file)
index 9016cfe..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-
- This patch fixes bug #1003 where putting the message output from 
- a Verify job into the catalog results in a recursive loop.  The problem
- seems to show up only with postgresql (to be verified).
-
- Apply it to version 2.2.5 (or probably any previous 2.2.x version) with
-
- cd <bacula-source>
- ./configure <your-options>  not necessary if already configured
- patch -p0 <2.2.5-verify-loop.patch
- make
- ...
- make install
-
-
-Index: src/dird/verify.c
-===================================================================
---- src/dird/verify.c  (revision 5814)
-+++ src/dird/verify.c  (working copy)
-@@ -767,11 +767,11 @@
-       return 1;
-    }
-    if (!jcr->fn_printed) {
--      Jmsg(jcr, M_INFO, 0, _("\nThe following files are in the Catalog but not on %s:\n"),
-+      Qmsg(jcr, M_INFO, 0, _("\nThe following files are in the Catalog but not on %s:\n"),
-        jcr->JobLevel == L_VERIFY_VOLUME_TO_CATALOG ? "the Volume(s)" : "disk");
-       jcr->fn_printed = true;
-    }
--   Jmsg(jcr, M_INFO, 0, "      %s%s\n", row[0]?row[0]:"", row[1]?row[1]:"");
-+   Qmsg(jcr, M_INFO, 0, "      %s%s\n", row[0]?row[0]:"", row[1]?row[1]:"");
-    return 0;
- }
diff --git a/bacula/patches/2.2.6-scratch.patch b/bacula/patches/2.2.6-scratch.patch
new file mode 100644 (file)
index 0000000..d6da1cd
--- /dev/null
@@ -0,0 +1,29 @@
+
+ This patch prevents the "status dir" command from trying to use a scratch
+ volume and possibly moving it from one pool to another.  This patch fixes
+ bug #1019.
+
+ Apply the patch to 2.2.6 (and possibly any 2.2.x version with):
+
+ cd <bacula-source>
+ patch -p0 <2.2.6-scratch.patch
+ ./configure <your-options>
+ make
+ ...
+ make install
+
+
+
+Index: src/dird/next_vol.c
+===================================================================
+--- src/dird/next_vol.c        (revision 5999)
++++ src/dird/next_vol.c        (working copy)
+@@ -97,7 +97,7 @@
+                   prune_volumes(jcr, InChanger, mr);
+                }
+                ok = recycle_oldest_purged_volume(jcr, InChanger, mr);
+-               if (!ok) {
++               if (!ok && create) {
+                   Dmsg4(050, "after prune volumes_vol ok=%d index=%d InChanger=%d Vstat=%s\n",
+                         ok, index, InChanger, mr->VolStatus);
+                   /*
diff --git a/bacula/patches/2.2.x/2.2.4-ansi-label.patch b/bacula/patches/2.2.x/2.2.4-ansi-label.patch
new file mode 100644 (file)
index 0000000..d68e618
--- /dev/null
@@ -0,0 +1,77 @@
+ This patch fixes bug #954.
+ WEOF on non-appendable error when trying to label a tape with ANSI labels turned on.
+
+ Apply it to version 2.2.4 (possibly earlier versions with):
+
+ cd <bacula-source>
+ patch -p0 <2.2.4-verify.patch
+ ./configure (your options)
+ make
+ ...
+ make install
+
+Index: block.c
+===================================================================
+--- src/stored/block.c (revision 5615)
++++ src/stored/block.c (revision 5615)
+@@ -273,6 +273,7 @@
+       dev->dev_errno = EIO;
+       Mmsg4(dev->errmsg, _("Volume data error at %u:%u! Wanted ID: \"%s\", got \"%s\". Buffer discarded.\n"),
+           dev->file, dev->block_num, BLKHDR2_ID, Id);
++      Dmsg1(50, "%s", dev->errmsg);
+       if (block->read_errors == 0 || verbose >= 2) {
+          Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg);
+       }
+@@ -1008,8 +1009,19 @@
+       dev->set_ateof();
+       return false;             /* return eof */
+    }
++
+    /* Continue here for successful read */
++
+    block->read_len = stat;      /* save length read */
++   if (dev->at_eof() && block->read_len == 80 && 
++        (dcr->VolCatInfo.LabelType != B_BACULA_LABEL ||
++         dcr->device->label_type != B_BACULA_LABEL)) {
++      /* ***FIXME*** should check label */
++      Dmsg2(100, "Ignore 80 byte ANSI label at %u:%u\n", dev->file, dev->block_num);
++      dev->clear_eof();
++      goto reread;             /* skip ANSI/IBM label */
++   }
++                                          
+    if (block->read_len < BLKHDR2_LENGTH) {
+       dev->dev_errno = EIO;
+       Mmsg4(dev->errmsg, _("Volume data error at %u:%u! Very short block of %d bytes on device %s discarded.\n"),
+
+Index: label.c
+===================================================================
+--- src/stored/label.c (revision 5602)
++++ src/stored/label.c (working copy)
+@@ -119,7 +119,6 @@
+    bstrncpy(dev->VolHdr.Id, "**error**", sizeof(dev->VolHdr.Id));
+   /* Read ANSI/IBM label if so requested */
+-  
+   want_ansi_label = dcr->VolCatInfo.LabelType != B_BACULA_LABEL ||
+                     dcr->device->label_type != B_BACULA_LABEL;
+   if (want_ansi_label || dev->has_cap(CAP_CHECKLABELS)) {
+@@ -344,6 +343,9 @@
+       }
+    }
++   /* Temporarily mark in append state to enable writing */
++   dev->set_append();
++
+    /* Create PRE_LABEL or VOL_LABEL if DVD */
+    create_volume_label(dev, VolName, PoolName, dvdnow);
+@@ -364,8 +366,6 @@
+    create_volume_label_record(dcr, dcr->rec);
+    dcr->rec->Stream = 0;
+-   /* Temporarily mark in append state to enable writing */
+-   dev->set_append();
+    if (!write_record_to_block(dcr->block, dcr->rec)) {
+       Dmsg2(130, "Bad Label write on %s: ERR=%s\n", dev->print_name(), dev->print_errmsg());
+       goto bail_out;
diff --git a/bacula/patches/2.2.x/2.2.4-lost-block.patch b/bacula/patches/2.2.x/2.2.4-lost-block.patch
new file mode 100644 (file)
index 0000000..fbf7122
--- /dev/null
@@ -0,0 +1,30 @@
+
+ This patch fixes a race condition where a Job is terminating at the same
+ time that another job reaches the end of Volume. In that case, sometimes
+ the last block or two are not written to the Volume.  This seems to be 
+ relatively rare, but does result in data loss.  This fixes bug #964.
+
+ Apply the patch to Bacula version 2.2.4 (or possibly any previous 2.2.x 
+ version) with:
+
+ cd <bacula-source>
+ patch -p0 <2.2.4-lost-block.patch
+ ./configure (your options)
+ make
+ ...
+ make install
+
+
+Index: src/stored/append.c
+===================================================================
+--- src/stored/append.c        (revision 5602)
++++ src/stored/append.c        (working copy)
+@@ -287,7 +287,7 @@
+     * Check if we can still write. This may not be the case
+     *  if we are at the end of the tape or we got a fatal I/O error.
+     */
+-   if (dev->can_write()) {
++   if (ok || dev->can_write()) {
+       if (!write_session_label(dcr, EOS_LABEL)) {
+          Jmsg1(jcr, M_FATAL, 0, _("Error writting end session label. ERR=%s\n"),
+                dev->bstrerror());
diff --git a/bacula/patches/2.2.x/2.2.4-parse-command.patch b/bacula/patches/2.2.x/2.2.4-parse-command.patch
new file mode 100644 (file)
index 0000000..312dd29
--- /dev/null
@@ -0,0 +1,28 @@
+
+ This patch resolves a command parser issue 
+ causing a director segfault when using something
+ like "run job 1 2"
+
+ Apply to version 2.2.4 (and perhaps older 2.2.x versions) with
+
+ cd <bacula-source>
+ patch -p0 <2.2.4-parse-command.patch
+ ./configure (your options)
+ make
+ ...
+ make install
+
+
+Index: src/dird/ua_run.c
+===================================================================
+--- src/dird/ua_run.c  (révision 5616)
++++ src/dird/ua_run.c  (copie de travail)
+@@ -933,7 +933,7 @@
+             /* Note, yes and run have no value, so do not fail */
+             if (!ua->argv[i] && j != YES_POS /*yes*/) {
+                ua->send_msg(_("Value missing for keyword %s\n"), ua->argk[i]);
+-               return true;
++               return false;
+             }
+             Dmsg1(800, "Got keyword=%s\n", NPRT(kw[j]));
+             switch (j) {
diff --git a/bacula/patches/2.2.x/2.2.4-poll-mount.patch b/bacula/patches/2.2.x/2.2.4-poll-mount.patch
new file mode 100644 (file)
index 0000000..a4676e9
--- /dev/null
@@ -0,0 +1,27 @@
+
+ This patch resolves bug #908 where a tape is not properly mounted
+ (recognized) during a poll.
+
+ Apply to version 2.2.4 (and perhaps older 2.2.x versions) with
+  
+ cd <bacula-source>
+ patch -p0 <2.2.4-poll-mount.patch
+ ./configure (your options)
+ make
+ ...
+ make install
+
+Index: src/stored/dev.c
+===================================================================
+--- src/stored/dev.c   (revision 5553)
++++ src/stored/dev.c   (working copy)
+@@ -1844,7 +1844,8 @@
+    /* Clean up device packet so it can be reused */
+    clear_opened();
+-   state &= ~(ST_LABEL|ST_READ|ST_APPEND|ST_EOT|ST_WEOT|ST_EOF);
++   state &= ~(ST_LABEL|ST_READ|ST_APPEND|ST_EOT|ST_WEOT|ST_EOF|
++              ST_MOUNTED|ST_MEDIA|ST_SHORT|ST_FREESPACE_OK|ST_PART_SPOOLED);
+    label_type = B_BACULA_LABEL;
+    file = block_num = 0;
+    file_size = 0;
diff --git a/bacula/patches/2.2.x/2.2.4-replace.patch b/bacula/patches/2.2.x/2.2.4-replace.patch
new file mode 100644 (file)
index 0000000..58e4e51
--- /dev/null
@@ -0,0 +1,24 @@
+
+ This patch resolves bug #969 where the user can't change the
+ replace option in the restore menu
+
+ Apply to version 2.2.4 (and perhaps older 2.2.x versions) with
+
+ cd <bacula-source>
+ patch -p0 <2.2.4-replace.patch
+ ./configure (your options)
+ make
+ ...
+ make install
+
+--- src/dird/ua_run.c   (révision 5721)
++++ src/dird/ua_run.c   (copie de travail)
+@@ -424,6 +424,7 @@
+          }
+          opt = do_prompt(ua, "", _("Select replace option"), NULL, 0);
+          if (opt >=  0) {
++            rc.replace = ReplaceOptions[opt].name;
+             jcr->replace = ReplaceOptions[opt].token;
+          }
+          goto try_again;
+
diff --git a/bacula/patches/2.2.x/2.2.4-restore.patch b/bacula/patches/2.2.x/2.2.4-restore.patch
new file mode 100644 (file)
index 0000000..3ef991e
--- /dev/null
@@ -0,0 +1,49 @@
+
+ This patch resolves bug #955 where the director segfault when
+ where= option isn't specified anywhere.
+
+ Apply to version 2.2.4 (and perhaps older 2.2.x versions) with
+
+ cd <bacula-source>
+ patch -p0 <2.2.4-restore.patch
+ ./configure (your options)
+ make
+ ...
+ make install
+
+
+Index: src/dird/restore.c
+===================================================================
+--- src/dird/restore.c (revision 5601)
++++ src/dird/restore.c (working copy)
+@@ -173,7 +173,7 @@
+    }
+    /* Send restore command */
+-   char replace, *where, *cmd=NULL;
++   char replace, *where, *cmd;
+    char empty = '\0';
+    if (jcr->replace != 0) {
+@@ -183,8 +183,6 @@
+    } else {
+       replace = REPLACE_ALWAYS;       /* always replace */
+    }
+-   
+-   where = &empty;                    /* default */
+    if (jcr->RegexWhere) {
+       where = jcr->RegexWhere;             /* override */
+@@ -199,7 +197,11 @@
+    } else if (jcr->job->RestoreWhere) {
+       where = jcr->job->RestoreWhere; /* no override take from job */
+       cmd = restorecmd;
+-   } 
++
++   } else {                         /* nothing was specified */
++      where = &empty;               /* use default */
++      cmd   = restorecmd;                  
++   }
+    
+    jcr->prefix_links = jcr->job->PrefixLinks;
diff --git a/bacula/patches/2.2.x/2.2.4-sd-auth-fail.patch b/bacula/patches/2.2.x/2.2.4-sd-auth-fail.patch
new file mode 100644 (file)
index 0000000..2e506e7
--- /dev/null
@@ -0,0 +1,159 @@
+
+ This patch applies to Bacula version 2.2.4 (possibly earlier 2.2.x versions)
+ and fixes a Storage daemon authentication problem with the FD.  This fixes
+ bug #953.  The patch also adds a bit of additional debug code and significantly
+ strengthens the SD session key.
+
+ Apply it to 2.2.4 with:
+
+  cd <bacula-source>
+  patch -p0 <2.2.4-sd-auth-fail.patch
+  make
+  ...
+  make install
+
+
+Index: src/stored/job.c
+===================================================================
+--- src/stored/job.c   (revision 5602)
++++ src/stored/job.c   (working copy)
+@@ -73,6 +73,7 @@
+ {
+    int JobId;
+    char auth_key[100];
++   char seed[100];
+    BSOCK *dir = jcr->dir_bsock;
+    POOL_MEM job_name, client_name, job, fileset_name, fileset_md5;
+    int JobType, level, spool_attributes, no_attributes, spool_data;
+@@ -91,7 +92,7 @@
+               &write_part_after_job, &PreferMountedVols);
+    if (stat != 13) {
+       pm_strcpy(jcr->errmsg, dir->msg);
+-      bnet_fsend(dir, BAD_job, stat, jcr->errmsg);
++      dir->fsend(BAD_job, stat, jcr->errmsg);
+       Dmsg1(100, ">dird: %s", dir->msg);
+       set_jcr_job_status(jcr, JS_ErrorTerminated);
+       return false;
+@@ -134,9 +135,10 @@
+    /*
+     * Pass back an authorization key for the File daemon
+     */
+-   make_session_key(auth_key, NULL, 1);
+-   bnet_fsend(dir, OKjob, jcr->VolSessionId, jcr->VolSessionTime, auth_key);
+-   Dmsg1(100, ">dird: %s", dir->msg);
++   bsnprintf(seed, sizeof(seed), "%p%d", jcr, JobId);
++   make_session_key(auth_key, seed, 1);
++   dir->fsend(OKjob, jcr->VolSessionId, jcr->VolSessionTime, auth_key);
++   Dmsg2(100, ">dird jid=%u: %s", (uint32_t)jcr->JobId, dir->msg);
+    jcr->sd_auth_key = bstrdup(auth_key);
+    memset(auth_key, 0, sizeof(auth_key));
+    generate_daemon_event(jcr, "JobStart");
+@@ -169,17 +171,18 @@
+    timeout.tv_nsec = tv.tv_usec * 1000;
+    timeout.tv_sec = tv.tv_sec + me->client_wait;
+-   Dmsg2(100, "%s waiting %d sec for FD to contact SD\n", 
+-        jcr->Job, (int)me->client_wait);
++   Dmsg3(050, "%s waiting %d sec for FD to contact SD key=%s\n",
++         jcr->Job, (int)me->client_wait, jcr->sd_auth_key);
++
+    /*
+     * Wait for the File daemon to contact us to start the Job,
+     *  when he does, we will be released, unless the 30 minutes
+     *  expires.
+     */
+    P(mutex);
+-   for ( ; !job_canceled(jcr); ) {
++   while ( !jcr->authenticated && !job_canceled(jcr) ) {
+       errstat = pthread_cond_timedwait(&jcr->job_start_wait, &mutex, &timeout);
+-      if (errstat == 0 || errstat == ETIMEDOUT) {
++      if (errstat == ETIMEDOUT || errstat == EINVAL || errstat == EPERM) {
+          break;
+       }
+    }
+@@ -195,7 +198,7 @@
+ }
+ /*
+- * After receiving a connection (in job.c) if it is
++ * After receiving a connection (in dircmd.c) if it is
+  *   from the File daemon, this routine is called.
+  */
+ void handle_filed_connection(BSOCK *fd, char *job_name)
+@@ -204,8 +207,8 @@
+    bmicrosleep(0, 50000);             /* wait 50 millisecs */
+    if (!(jcr=get_jcr_by_full_name(job_name))) {
+-      Jmsg1(NULL, M_FATAL, 0, _("Job name not found: %s\n"), job_name);
+-      Dmsg1(100, "Job name not found: %s\n", job_name);
++      Jmsg1(NULL, M_FATAL, 0, _("FD connect failed: Job name not found: %s\n"), job_name);
++      Dmsg1(3, "**** Job \"%s\" not found", job_name);
+       return;
+    }
+@@ -216,7 +219,7 @@
+    if (jcr->authenticated) {
+       Jmsg2(jcr, M_FATAL, 0, _("Hey!!!! JobId %u Job %s already authenticated.\n"),
+-         jcr->JobId, jcr->Job);
++         (uint32_t)jcr->JobId, jcr->Job);
+       free_jcr(jcr);
+       return;
+    }
+@@ -229,7 +232,7 @@
+       Jmsg(jcr, M_FATAL, 0, _("Unable to authenticate File daemon\n"));
+    } else {
+       jcr->authenticated = true;
+-      Dmsg1(110, "OK Authentication Job %s\n", jcr->Job);
++      Dmsg2(110, "OK Authentication jid=%u Job %s\n", (uint32_t)jcr->JobId, jcr->Job);
+    }
+    if (!jcr->authenticated) {
+@@ -274,9 +277,9 @@
+             }  
+             ok = dir_update_device(jcr, device->dev);
+             if (ok) {
+-               ok = bnet_fsend(dir, OK_query);
++               ok = dir->fsend(OK_query);
+             } else {
+-               bnet_fsend(dir, NO_query);
++               dir->fsend(NO_query);
+             }
+             return ok;
+          }
+@@ -289,9 +292,9 @@
+             }
+             ok = dir_update_changer(jcr, changer);
+             if (ok) {
+-               ok = bnet_fsend(dir, OK_query);
++               ok = dir->fsend(OK_query);
+             } else {
+-               bnet_fsend(dir, NO_query);
++               dir->fsend(NO_query);
+             }
+             return ok;
+          }
+@@ -299,12 +302,12 @@
+       /* If we get here, the device/autochanger was not found */
+       unbash_spaces(dir->msg);
+       pm_strcpy(jcr->errmsg, dir->msg);
+-      bnet_fsend(dir, NO_device, dev_name.c_str());
++      dir->fsend(NO_device, dev_name.c_str());
+       Dmsg1(100, ">dird: %s\n", dir->msg);
+    } else {
+       unbash_spaces(dir->msg);
+       pm_strcpy(jcr->errmsg, dir->msg);
+-      bnet_fsend(dir, BAD_query, jcr->errmsg);
++      dir->fsend(BAD_query, jcr->errmsg);
+       Dmsg1(100, ">dird: %s\n", dir->msg);
+    }
+@@ -322,7 +325,7 @@
+ {
+    Dmsg1(900, "stored_free_jcr JobId=%u\n", jcr->JobId);
+    if (jcr->file_bsock) {
+-      bnet_close(jcr->file_bsock);
++      jcr->file_bsock->close();
+       jcr->file_bsock = NULL;
+    }
+    if (jcr->job_name) {
diff --git a/bacula/patches/2.2.x/2.2.4-sql.patch b/bacula/patches/2.2.x/2.2.4-sql.patch
new file mode 100644 (file)
index 0000000..24de099
--- /dev/null
@@ -0,0 +1,476 @@
+
+ This patch fixes several problems: it fixes incorrect or incomplete error
+ messages; it fixes a problem opening the SQLite3 database when multiple
+ simultaneous jobs were running; it fixes a bug with certain versions of
+ MySQL where batch inserts failed because of table name character case
+ (upper/lower) differences.
+
+ It can be applied to version 2.2.4 (and possibly earlier 2.2.x versions)
+ with:
+
+   cd <bacula-source>     
+   patch -p0 <2.2.4-sql.patch
+   ./configure (your options)
+   make
+   ...
+   make install
+
+
+           
+Index: src/cats/sql.c
+===================================================================
+--- src/cats/sql.c     (revision 5687)
++++ src/cats/sql.c     (working copy)
+@@ -115,7 +115,6 @@
+    bacula_db_version = 0;
+    if (!db_sql_query(mdb, query, int_handler, (void *)&bacula_db_version)) {
+-      Mmsg(mdb->errmsg, "Database not created or server not running.\n");
+       Jmsg(jcr, M_FATAL, 0, "%s", mdb->errmsg);
+       return false;
+    }
+Index: src/cats/sqlite.c
+===================================================================
+--- src/cats/sqlite.c  (revision 5687)
++++ src/cats/sqlite.c  (working copy)
+@@ -148,6 +148,7 @@
+    int len;
+    struct stat statbuf;
+    int errstat;
++   int retry = 0;
+    P(mutex);
+    if (mdb->connected) {
+@@ -157,8 +158,9 @@
+    mdb->connected = FALSE;
+    if ((errstat=rwl_init(&mdb->lock)) != 0) {
++      berrno be;
+       Mmsg1(&mdb->errmsg, _("Unable to initialize DB lock. ERR=%s\n"),
+-            strerror(errstat));
++            be.bstrerror(errstat));
+       V(mutex);
+       return 0;
+    }
+@@ -178,28 +180,28 @@
+       return 0;
+    }
++   for (mdb->db=NULL; !mdb->db && retry++ < 10; ) {
+ #ifdef HAVE_SQLITE3
+-   int stat = sqlite3_open(db_name, &mdb->db);
+-   if (stat != SQLITE_OK) {
+-      mdb->sqlite_errmsg = (char *)sqlite3_errmsg(mdb->db); 
+-      sqlite3_close(mdb->db);
+-      mdb->db = NULL;
+-   } else {
+-      mdb->sqlite_errmsg = NULL;
+-   }
+-#ifdef SQLITE3_INIT_QUERY
+-   db_sql_query(mdb, SQLITE3_INIT_QUERY, NULL, NULL);
+-#endif
+-
++      int stat = sqlite3_open(db_name, &mdb->db);
++      if (stat != SQLITE_OK) {
++         mdb->sqlite_errmsg = (char *)sqlite3_errmsg(mdb->db); 
++         sqlite3_close(mdb->db);
++         mdb->db = NULL;
++      } else {
++         mdb->sqlite_errmsg = NULL;
++      }
+ #else
+-   mdb->db = sqlite_open(
+-        db_name,                      /* database name */
+-        644,                          /* mode */
+-        &mdb->sqlite_errmsg);         /* error message */
++      mdb->db = sqlite_open(
++           db_name,                      /* database name */
++           644,                          /* mode */
++           &mdb->sqlite_errmsg);         /* error message */
+ #endif
+-   Dmsg0(300, "sqlite_open\n");
+-
++      Dmsg0(300, "sqlite_open\n");
++      if (!mdb->db) {
++         bmicrosleep(1, 0);
++      }
++   }
+    if (mdb->db == NULL) {
+       Mmsg2(&mdb->errmsg, _("Unable to open Database=%s. ERR=%s\n"),
+          db_name, mdb->sqlite_errmsg ? mdb->sqlite_errmsg : _("unknown"));
+@@ -209,10 +211,6 @@
+    }       
+    mdb->connected = true;
+    free(db_name);
+-   if (!check_tables_version(jcr, mdb)) {
+-      V(mutex);
+-      return 0;
+-   }
+    /* set busy handler to wait when we use mult_db_connections = 1 */
+ #ifdef HAVE_SQLITE3
+@@ -221,6 +219,16 @@
+    sqlite_busy_handler(mdb->db, my_busy_handler, NULL);
+ #endif
++#if  defined(HAVE_SQLITE3) && defined(SQLITE3_INIT_QUERY)
++   db_sql_query(mdb, SQLITE3_INIT_QUERY, NULL, NULL);
++#endif
++
++   if (!check_tables_version(jcr, mdb)) {
++      V(mutex);
++      return 0;
++   }
++
++
+    V(mutex);
+    return 1;
+ }
+@@ -448,16 +456,20 @@
+    return mdb->fields[mdb->field++];
+ }
+-char *my_sqlite_batch_lock_query = "BEGIN";
+-char *my_sqlite_batch_unlock_query = "COMMIT";
+-char *my_sqlite_batch_fill_path_query = "INSERT INTO Path (Path)          " 
+-                                        " SELECT DISTINCT Path FROM batch "
+-                                        " EXCEPT SELECT Path FROM Path    ";
++#ifdef HAVE_BATCH_FILE_INSERT
++const char *my_sqlite_batch_lock_query = "BEGIN";
++const char *my_sqlite_batch_unlock_query = "COMMIT";
+-char *my_sqlite_batch_fill_filename_query = "INSERT INTO Filename (Name)       " 
+-                                            " SELECT DISTINCT Name FROM batch  "
+-                                            " EXCEPT SELECT Name FROM Filename ";
++const char *my_sqlite_batch_fill_path_query = 
++   "INSERT INTO Path (Path)" 
++   " SELECT DISTINCT Path FROM batch"
++   " EXCEPT SELECT Path FROM Path";
++const char *my_sqlite_batch_fill_filename_query = 
++   "INSERT INTO Filename (Name)"
++   " SELECT DISTINCT Name FROM batch "
++   " EXCEPT SELECT Name FROM Filename";
++#endif /* HAVE_BATCH_FILE_INSERT */
+ #endif /* HAVE_SQLITE */
+Index: src/cats/cats.h
+===================================================================
+--- src/cats/cats.h    (revision 5687)
++++ src/cats/cats.h    (working copy)
+@@ -187,10 +187,10 @@
+ int        my_sqlite_query(B_DB *mdb, const char *cmd);
+ void       my_sqlite_field_seek(B_DB *mdb, int field);
+ SQL_FIELD *my_sqlite_fetch_field(B_DB *mdb);
+-extern char* my_sqlite_batch_lock_query;
+-extern char* my_sqlite_batch_unlock_query;
+-extern char* my_sqlite_batch_fill_filename_query;
+-extern char* my_sqlite_batch_fill_path_query;
++extern const char* my_sqlite_batch_lock_query;
++extern const char* my_sqlite_batch_unlock_query;
++extern const char* my_sqlite_batch_fill_filename_query;
++extern const char* my_sqlite_batch_fill_path_query;
+ #else
+@@ -317,10 +317,10 @@
+ int        my_sqlite_query(B_DB *mdb, const char *cmd);
+ void       my_sqlite_field_seek(B_DB *mdb, int field);
+ SQL_FIELD *my_sqlite_fetch_field(B_DB *mdb);
+-extern char* my_sqlite_batch_lock_query;
+-extern char* my_sqlite_batch_unlock_query;
+-extern char* my_sqlite_batch_fill_filename_query;
+-extern char* my_sqlite_batch_fill_path_query;
++extern const char* my_sqlite_batch_lock_query;
++extern const char* my_sqlite_batch_unlock_query;
++extern const char* my_sqlite_batch_fill_filename_query;
++extern const char* my_sqlite_batch_fill_path_query;
+ #else
+@@ -398,11 +398,11 @@
+ #define sql_batch_fill_path_query       my_mysql_batch_fill_path_query
+-extern char* my_mysql_batch_lock_path_query;
+-extern char* my_mysql_batch_lock_filename_query;
+-extern char* my_mysql_batch_unlock_tables_query;
+-extern char* my_mysql_batch_fill_filename_query;
+-extern char* my_mysql_batch_fill_path_query;
++extern const char* my_mysql_batch_lock_path_query;
++extern const char* my_mysql_batch_lock_filename_query;
++extern const char* my_mysql_batch_unlock_tables_query;
++extern const char* my_mysql_batch_fill_filename_query;
++extern const char* my_mysql_batch_fill_path_query;
+ extern void  my_mysql_free_result(B_DB *mdb);
+ #else
+@@ -486,11 +486,11 @@
+ int my_postgresql_batch_insert(JCR *jcr, B_DB *mdb, ATTR_DBR *ar);
+ char *my_postgresql_copy_escape(char *dest, char *src, size_t len);
+-extern char* my_pg_batch_lock_path_query;
+-extern char* my_pg_batch_lock_filename_query;
+-extern char* my_pg_batch_unlock_tables_query;
+-extern char* my_pg_batch_fill_filename_query;
+-extern char* my_pg_batch_fill_path_query;
++extern const char* my_pg_batch_lock_path_query;
++extern const char* my_pg_batch_lock_filename_query;
++extern const char* my_pg_batch_unlock_tables_query;
++extern const char* my_pg_batch_fill_filename_query;
++extern const char* my_pg_batch_fill_path_query;
+ /* "Generic" names for easier conversion */
+ #define sql_store_result(x)   ((x)->result)
+Index: src/cats/mysql.c
+===================================================================
+--- src/cats/mysql.c   (revision 5687)
++++ src/cats/mysql.c   (working copy)
+@@ -149,8 +149,9 @@
+    }
+    if ((errstat=rwl_init(&mdb->lock)) != 0) {
++      berrno be;
+       Mmsg1(&mdb->errmsg, _("Unable to initialize DB lock. ERR=%s\n"),
+-            strerror(errstat));
++            be.bstrerror(errstat));
+       V(mutex);
+       return 0;
+    }
+@@ -403,33 +404,27 @@
+    db_unlock(mdb);
+ }
+-char *my_mysql_batch_lock_path_query = "LOCK TABLES Path write,     " 
+-                                       "            batch write,    " 
+-                                       "            Path as p write ";
++#ifdef HAVE_BATCH_FILE_INSERT
++const char *my_mysql_batch_lock_path_query = 
++   "LOCK TABLES Path write, batch write, Path as p write";
+-char *my_mysql_batch_lock_filename_query = "LOCK TABLES Filename write,     "
+-                                           "            batch write,        "
+-                                           "            Filename as f write ";
++const char *my_mysql_batch_lock_filename_query = 
++   "LOCK TABLES Filename write, batch write, Filename as f write";
+-char *my_mysql_batch_unlock_tables_query = "UNLOCK TABLES";
++const char *my_mysql_batch_unlock_tables_query = "UNLOCK TABLES";
+-char *my_mysql_batch_fill_path_query = "INSERT INTO Path (Path)        "
+-                                       " SELECT a.Path FROM            " 
+-                                       "  (SELECT DISTINCT Path        "
+-                                       "     FROM batch) AS a          " 
+-                                       " WHERE NOT EXISTS              "
+-                                       "  (SELECT Path                 "
+-                                       "     FROM Path AS p            "
+-                                       "    WHERE p.Path = a.Path)     ";     
++const char *my_mysql_batch_fill_path_query = 
++   "INSERT INTO Path (Path) "
++    "SELECT a.Path FROM " 
++     "(SELECT DISTINCT Path FROM batch) AS a WHERE NOT EXISTS "
++     "(SELECT Path FROM Path AS p WHERE p.Path = a.Path)";     
+-char *my_mysql_batch_fill_filename_query = "INSERT INTO Filename (Name)       "
+-                                           "  SELECT a.Name FROM              " 
+-                                           "   (SELECT DISTINCT Name          "
+-                                           "      FROM batch) AS a            " 
+-                                           "  WHERE NOT EXISTS                "
+-                                           "   (SELECT Name                   "
+-                                           "      FROM Filename AS f          "
+-                                           "      WHERE f.Name = a.Name)      ";
++const char *my_mysql_batch_fill_filename_query = 
++   "INSERT INTO Filename (Name) "
++    "SELECT a.Name FROM " 
++     "(SELECT DISTINCT Name FROM batch) AS a WHERE NOT EXISTS "
++     "(SELECT Name FROM Filename AS f WHERE f.Name = a.Name)";
++#endif /* HAVE_BATCH_FILE_INSERT */
+ #endif /* HAVE_MYSQL */
+Index: src/cats/sql_create.c
+===================================================================
+--- src/cats/sql_create.c      (revision 5687)
++++ src/cats/sql_create.c      (working copy)
+@@ -668,6 +668,8 @@
+  *  };
+  */
++#ifdef HAVE_BATCH_FILE_INSERT
++
+ /*  All sql_batch_* functions are used to do bulk batch insert in File/Filename/Path
+  *  tables. This code can be activated by adding "#define HAVE_BATCH_FILE_INSERT 1"
+  *  in baconfig.h
+@@ -690,13 +692,13 @@
+    db_lock(mdb);
+    ok =  db_sql_query(mdb,
+-             " CREATE TEMPORARY TABLE batch "
+-             "        (fileindex integer,   "
+-             "        jobid integer,        "
+-             "        path blob,            "
+-             "        name blob,            "
+-             "        lstat tinyblob,       "
+-             "        md5 tinyblob)         ",NULL, NULL);
++             "CREATE TEMPORARY TABLE batch ("
++                "FileIndex integer,"
++                "JobId integer,"
++                "Path blob,"
++                "Name blob,"
++                "LStat tinyblob,"
++                "MD5 tinyblob)",NULL, NULL);
+    db_unlock(mdb);
+    return ok;
+ }
+@@ -746,7 +748,6 @@
+    return true;
+ }
+-#ifdef HAVE_BATCH_FILE_INSERT
+ /* 
+  * Returns 1 if OK
+  *         0 if failed
+@@ -794,7 +795,7 @@
+    
+    if (!db_sql_query(jcr->db_batch,sql_batch_fill_filename_query, NULL,NULL)) {
+       Jmsg(jcr,M_FATAL,0,"Can't fill Filename table %s\n",jcr->db_batch->errmsg);
+-      QUERY_DB(jcr, jcr->db_batch, sql_batch_unlock_tables_query);
++      db_sql_query(jcr->db_batch, sql_batch_unlock_tables_query, NULL, NULL);
+       return false;            
+    }
+@@ -804,12 +805,12 @@
+    }
+    
+    if (!db_sql_query(jcr->db_batch, 
+-       " INSERT INTO File (FileIndex, JobId, PathId, FilenameId, LStat, MD5)"
+-       "  SELECT batch.FileIndex, batch.JobId, Path.PathId,               " 
+-       "         Filename.FilenameId,batch.LStat, batch.MD5               "
+-       "  FROM batch                                                      "
+-       "    JOIN Path ON (batch.Path = Path.Path)                         "
+-       "    JOIN Filename ON (batch.Name = Filename.Name)                 ",
++       "INSERT INTO File (FileIndex, JobId, PathId, FilenameId, LStat, MD5)"
++         "SELECT batch.FileIndex, batch.JobId, Path.PathId, "
++                "Filename.FilenameId,batch.LStat, batch.MD5 "
++           "FROM batch "
++           "JOIN Path ON (batch.Path = Path.Path) "
++           "JOIN Filename ON (batch.Name = Filename.Name)",
+                      NULL,NULL))
+    {
+       Jmsg(jcr, M_FATAL, 0, "Can't fill File table %s\n", jcr->db_batch->errmsg);
+@@ -845,19 +846,24 @@
+                                       mdb->db_port,
+                                       mdb->db_socket,
+                                       1 /* multi_db = true */);
++      if (!jcr->db_batch) {
++         Mmsg1(&mdb->errmsg, _("Could not init batch database: \"%s\".\n"),
++                        jcr->db->db_name);
++         Jmsg1(jcr, M_FATAL, 0, "%s", mdb->errmsg);
++         return false;
++      }
+-      if (!jcr->db_batch || !db_open_database(jcr, jcr->db_batch)) {
+-         Jmsg(jcr, M_FATAL, 0, _("Could not open database \"%s\".\n"),
+-              jcr->db->db_name);
+-         if (jcr->db_batch) {
+-            Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db_batch));
+-         }
++      if (!db_open_database(jcr, jcr->db_batch)) {
++         Mmsg2(&mdb->errmsg,  _("Could not open database \"%s\": ERR=%s\n"),
++              jcr->db->db_name, db_strerror(jcr->db_batch));
++         Jmsg1(jcr, M_FATAL, 0, "%s", mdb->errmsg);
+          return false;
+       }      
+       
+       if (!sql_batch_start(jcr, jcr->db_batch)) {
+-         Jmsg(jcr, M_FATAL, 0, 
+-              "Can't start batch mode %s", db_strerror(jcr->db_batch));
++         Mmsg1(&mdb->errmsg, 
++              "Can't start batch mode: ERR=%s", db_strerror(jcr->db_batch));
++         Jmsg1(jcr, M_FATAL, 0, "%s", mdb->errmsg);
+          return false;
+       }
+       Dmsg3(100, "initdb ref=%d connected=%d db=%p\n", jcr->db_batch->ref_count,
+@@ -870,10 +876,10 @@
+     */
+    if (!(ar->Stream == STREAM_UNIX_ATTRIBUTES ||
+          ar->Stream == STREAM_UNIX_ATTRIBUTES_EX)) {
+-      Mmsg1(&bdb->errmsg, _("Attempt to put non-attributes into catalog. Stream=%d\n"),
++      Mmsg1(&mdb->errmsg, _("Attempt to put non-attributes into catalog. Stream=%d\n"),
+          ar->Stream);
+-      Jmsg(jcr, M_ERROR, 0, "%s", bdb->errmsg);
+-      return 0;
++      Jmsg(jcr, M_FATAL, 0, "%s", mdb->errmsg);
++      return false;
+    }
+    split_path_and_file(jcr, bdb, ar->fname);
+Index: src/cats/postgresql.c
+===================================================================
+--- src/cats/postgresql.c      (revision 5687)
++++ src/cats/postgresql.c      (working copy)
+@@ -605,13 +605,13 @@
+    Dmsg0(500, "my_postgresql_batch_start started\n");
+    if (my_postgresql_query(mdb,
+-                           " CREATE TEMPORARY TABLE batch "
+-                           "        (fileindex int,       "
+-                           "        jobid int,            "
+-                           "        path varchar,         "
+-                           "        name varchar,         "
+-                           "        lstat varchar,        "
+-                           "        md5 varchar)") == 1)
++                           "CREATE TEMPORARY TABLE batch ("
++                               "fileindex int,"
++                               "jobid int,"
++                               "path varchar,"
++                               "name varchar,"
++                               "lstat varchar,"
++                               "md5 varchar)") == 1)
+    {
+       Dmsg0(500, "my_postgresql_batch_start failed\n");
+       return 1;
+@@ -785,22 +785,29 @@
+    return dest;
+ }
+-char *my_pg_batch_lock_path_query = "BEGIN; LOCK TABLE Path IN SHARE ROW EXCLUSIVE MODE";
++#ifdef HAVE_BATCH_FILE_INSERT
++const char *my_pg_batch_lock_path_query = 
++   "BEGIN; LOCK TABLE Path IN SHARE ROW EXCLUSIVE MODE";
+-char *my_pg_batch_lock_filename_query = "BEGIN; LOCK TABLE Filename IN SHARE ROW EXCLUSIVE MODE";
++const char *my_pg_batch_lock_filename_query = 
++   "BEGIN; LOCK TABLE Filename IN SHARE ROW EXCLUSIVE MODE";
+-char *my_pg_batch_unlock_tables_query = "COMMIT";
++const char *my_pg_batch_unlock_tables_query = "COMMIT";
+-char *my_pg_batch_fill_path_query = "INSERT INTO Path (Path)                                    "
+-                                    "  SELECT a.Path FROM                                       "
+-                                    "      (SELECT DISTINCT Path FROM batch) AS a               "
+-                                    "  WHERE NOT EXISTS (SELECT Path FROM Path WHERE Path = a.Path) ";
++const char *my_pg_batch_fill_path_query = 
++   "INSERT INTO Path (Path) "
++    "SELECT a.Path FROM "
++     "(SELECT DISTINCT Path FROM batch) AS a "
++      "WHERE NOT EXISTS (SELECT Path FROM Path WHERE Path = a.Path) ";
+-char *my_pg_batch_fill_filename_query = "INSERT INTO Filename (Name)        "
+-                                        "  SELECT a.Name FROM               "
+-                                        "    (SELECT DISTINCT Name FROM batch) as a "
+-                                        "    WHERE NOT EXISTS               "
+-                                        "      (SELECT Name FROM Filename WHERE Name = a.Name)";
++const char *my_pg_batch_fill_filename_query = 
++   "INSERT INTO Filename (Name) "
++    "SELECT a.Name FROM "
++     "(SELECT DISTINCT Name FROM batch) as a "
++      "WHERE NOT EXISTS "
++       "(SELECT Name FROM Filename WHERE Name = a.Name)";
++#endif /* HAVE_BATCH_FILE_INSERT */
++
+ #endif /* HAVE_POSTGRESQL */
diff --git a/bacula/patches/2.2.x/2.2.4-verify.patch b/bacula/patches/2.2.x/2.2.4-verify.patch
new file mode 100644 (file)
index 0000000..21e9af3
--- /dev/null
@@ -0,0 +1,75 @@
+ This patch fixes bug #958 A Verify catalog Job that has differences reports Verify OK.
+
+ Apply it to version 2.2.4 (possibly earlier versions with):
+
+ cd <bacula-source>
+ patch -p0 <2.2.4-verify.patch
+ ./configure (your options)
+ make
+ ...
+ make install
+
+Index: src/dird/verify.c
+===================================================================
+--- src/dird/verify.c  (revision 5553)
++++ src/dird/verify.c  (working copy)
+@@ -332,13 +332,10 @@
+    }
+    stat = wait_for_job_termination(jcr);
+-   if (stat == JS_Terminated) {
+-      verify_cleanup(jcr, stat);
+-      return true;
+-   }
++   verify_cleanup(jcr, stat);
++   return true;
+ bail_out:
+-   verify_cleanup(jcr, JS_ErrorTerminated);
+    return false;
+ }
+@@ -421,7 +418,7 @@
+    jobstatus_to_ascii(jcr->FDJobStatus, fd_term_msg, sizeof(fd_term_msg));
+    if (jcr->JobLevel == L_VERIFY_VOLUME_TO_CATALOG) {
+       jobstatus_to_ascii(jcr->SDJobStatus, sd_term_msg, sizeof(sd_term_msg));
+-   Jmsg(jcr, msg_type, 0, _("Bacula %s %s (%s): %s\n"
++      Jmsg(jcr, msg_type, 0, _("Bacula %s %s (%s): %s\n"
+ "  Build OS:               %s %s %s\n"
+ "  JobId:                  %d\n"
+ "  Job:                    %s\n"
+@@ -456,7 +453,7 @@
+          sd_term_msg,
+          term_msg);
+    } else {
+-   Jmsg(jcr, msg_type, 0, _("Bacula %s %s (%s): %s\n"
++      Jmsg(jcr, msg_type, 0, _("Bacula %s %s (%s): %s\n"
+ "  Build:                  %s %s %s\n"
+ "  JobId:                  %d\n"
+ "  Job:                    %s\n"
+@@ -750,7 +747,9 @@
+       stat = JS_Differences;
+    }
+    free_pool_memory(fname);
+-   set_jcr_job_status(jcr, stat);
++   if (!job_canceled(jcr)) {
++      jcr->JobStatus = stat;
++   }
+    return stat == JS_Terminated;
+ }
+Index: src/lib/jcr.c
+===================================================================
+--- src/lib/jcr.c      (revision 5553)
++++ src/lib/jcr.c      (working copy)
+@@ -614,9 +614,8 @@
+          /* Override more minor status */
+          jcr->JobStatus = JobStatus;
+          break;
+-      default:
+-         break;
+       }
++      break;
+    default:
+       jcr->JobStatus = JobStatus;
+    }
diff --git a/bacula/patches/2.2.x/2.2.5-deamon.patch b/bacula/patches/2.2.x/2.2.5-deamon.patch
new file mode 100644 (file)
index 0000000..6e82f1e
--- /dev/null
@@ -0,0 +1,40 @@
+
+ This patch fixes the default behavior of a non-DEVELOPER version of Bacula
+ to close STDIN, STDOUT, and STDERR so that an ssh that starts bacula
+ will not hang.  It also fixes a crash in bat when bat is executed and
+ cannot connect to the Director (e.g. it is not running).
+ This patch fixes bugs #991 and #993.
+
+ Apply this fix to Bacula version 2.2.5 with:
+
+ cd <bacula-source>
+ patch -p0 <2.2.5-daemon.patch
+ ./configure (your options)
+ make
+ ...
+ make install
+
+
+Index: src/lib/message.c
+===================================================================
+--- src/lib/message.c  (revision 5744)
++++ src/lib/message.c  (working copy)
+@@ -52,7 +52,8 @@
+  */
+ const char *working_directory = NULL;       /* working directory path stored here */
+ int verbose = 0;                      /* increase User messages */
+-int debug_level = 1;                  /* debug level */
++/* Keep debug level set to zero by default */
++int debug_level = 0;                  /* debug level */
+ time_t daemon_start_time = 0;         /* Daemon start time */
+ const char *version = VERSION " (" BDATE ")";
+ char my_name[30];                     /* daemon name is stored here */
+@@ -1338,7 +1339,7 @@
+       jcr = get_jcr_from_tsd();
+    }
+    /* If no jcr or dequeuing send to daemon to avoid recursion */
+-   if (!jcr || jcr->dequeuing) {
++   if ((jcr && !jcr->msg_queue) || !jcr || jcr->dequeuing) {
+       /* jcr==NULL => daemon message, safe to send now */
+       Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
+       free(item);
diff --git a/bacula/patches/2.2.x/2.2.5-hb.patch b/bacula/patches/2.2.x/2.2.5-hb.patch
new file mode 100644 (file)
index 0000000..b8d81c8
--- /dev/null
@@ -0,0 +1,186 @@
+
+ This patch fixes bug #947 where a large number of emails were generated
+ because the heartbeat interval was small and the tape in the drive did
+ not correspond to the one wanted by Bacula.
+
+ Apply the patch to version 2.2.5 (and probably any 2.2.x version) with:
+
+ cd <bacula-source>
+ ./configure <your options>
+ patch -p0 <2.2.5-hb.patch
+ make
+ ...
+ make install
+
+
+Index: src/stored/wait.c
+===================================================================
+--- src/stored/wait.c  (revision 5814)
++++ src/stored/wait.c  (working copy)
+@@ -40,9 +40,8 @@
+ #include "bacula.h"                   /* pull in global headers */
+ #include "stored.h"                   /* pull in Storage Deamon headers */
+-//static bool double_jcr_wait_time(JCR *jcr);
++const int dbglvl = 400;
+-
+ /*
+  * Wait for SysOp to mount a tape on a specific device
+  *
+@@ -62,7 +61,7 @@
+    JCR *jcr = dcr->jcr;
+    dev->dlock();  
+-   Dmsg1(100, "Enter blocked=%s\n", dev->print_blocked());
++   Dmsg1(dbglvl, "Enter blocked=%s\n", dev->print_blocked());
+    unmounted = is_device_unmounted(dev);
+    dev->poll = false;
+@@ -84,27 +83,28 @@
+    }
+    if (!unmounted) {
+-      Dmsg1(400, "blocked=%s\n", dev->print_blocked());
++      Dmsg1(dbglvl, "blocked=%s\n", dev->print_blocked());
+       dev->dev_prev_blocked = dev->blocked();
+       dev->set_blocked(BST_WAITING_FOR_SYSOP); /* indicate waiting for mount */
+    }
+    for ( ; !job_canceled(jcr); ) {
+-      time_t now, start;
++      time_t now, start, total_waited;
+       gettimeofday(&tv, &tz);
+       timeout.tv_nsec = tv.tv_usec * 1000;
+       timeout.tv_sec = tv.tv_sec + add_wait;
+-      Dmsg4(400, "I'm going to sleep on device %s. HB=%d wait=%d add_wait=%d\n", 
+-         dev->print_name(), (int)me->heartbeat_interval, dev->wait_sec, add_wait);
++      Dmsg4(dbglvl, "I'm going to sleep on device %s. HB=%d rem_wait=%d add_wait=%d\n", 
++         dev->print_name(), (int)me->heartbeat_interval, dev->rem_wait_sec, add_wait);
+       start = time(NULL);
+       /* Wait required time */
+       stat = pthread_cond_timedwait(&dev->wait_next_vol, &dev->m_mutex, &timeout);
+-      Dmsg2(400, "Wokeup from sleep on device stat=%d blocked=%s\n", stat,
++      Dmsg2(dbglvl, "Wokeup from sleep on device stat=%d blocked=%s\n", stat,
+          dev->print_blocked());
+       now = time(NULL);
++      total_waited = now - first_start;
+       dev->rem_wait_sec -= (now - start);
+       /* Note, this always triggers the first time. We want that. */
+@@ -113,7 +113,7 @@
+             /* send heartbeats */
+             if (jcr->file_bsock) {
+                jcr->file_bsock->signal(BNET_HEARTBEAT);
+-               Dmsg0(400, "Send heartbeat to FD.\n");
++               Dmsg0(dbglvl, "Send heartbeat to FD.\n");
+             }
+             if (jcr->dir_bsock) {
+                jcr->dir_bsock->signal(BNET_HEARTBEAT);
+@@ -131,7 +131,7 @@
+       if (dev->rem_wait_sec <= 0) {  /* on exceeding wait time return */
+-         Dmsg0(400, "Exceed wait time.\n");
++         Dmsg0(dbglvl, "Exceed wait time.\n");
+          stat = W_TIMEOUT;
+          break;
+       }
+@@ -142,8 +142,8 @@
+       unmounted = is_device_unmounted(dev);
+       if (!unmounted && dev->vol_poll_interval &&
+-          (now - first_start >= dev->vol_poll_interval)) {
+-         Dmsg1(400, "In wait blocked=%s\n", dev->print_blocked());
++          (total_waited >= dev->vol_poll_interval)) {
++         Dmsg1(dbglvl, "poll return in wait blocked=%s\n", dev->print_blocked());
+          dev->poll = true;            /* returning a poll event */
+          stat = W_POLL;
+          break;
+@@ -152,6 +152,7 @@
+        * Check if user mounted the device while we were waiting
+        */
+       if (dev->blocked() == BST_MOUNT) {   /* mount request ? */
++         Dmsg0(dbglvl, "Mounted return.\n");
+          stat = W_MOUNT;
+          break;
+       }
+@@ -160,30 +161,39 @@
+        * If we did not timeout, then some event happened, so
+        *   return to check if state changed.   
+        */
+-      if (stat != 0) {
++      if (stat != ETIMEDOUT) {
++         berrno be;
++         Dmsg2(dbglvl, "Wake return. stat=%d. ERR=%s\n", stat, be.bstrerror(stat));
+          stat = W_WAKE;          /* someone woke us */
+          break;
+       }
+       /* 
+        * At this point, we know we woke up because of a timeout,
+-       *   that was due to a heartbeat, so we just update
+-       *   the wait counters and continue.
++       *   that was due to a heartbeat, because any other reason would
++       *   have caused us to return, so update the wait counters and continue.
+        */
+-      add_wait = dev->wait_sec - (now - start);
++      add_wait = dev->rem_wait_sec;
++      if (me->heartbeat_interval && add_wait > me->heartbeat_interval) {
++         add_wait = me->heartbeat_interval;
++      }
++      /* If the user did not unmount the tape and we are polling, ensure
++       *  that we poll at the correct interval.
++       */
++      if (!unmounted && dev->vol_poll_interval && 
++           add_wait > dev->vol_poll_interval - total_waited) {
++         add_wait = dev->vol_poll_interval - total_waited;
++      }
+       if (add_wait < 0) {
+          add_wait = 0;
+       }
+-      if (me->heartbeat_interval && add_wait > me->heartbeat_interval) {
+-         add_wait = me->heartbeat_interval;
+-      }
+    }
+    if (!unmounted) {
+       dev->set_blocked(dev->dev_prev_blocked);    /* restore entry state */
+-      Dmsg1(400, "set %s\n", dev->print_blocked());
++      Dmsg1(dbglvl, "set %s\n", dev->print_blocked());
+    }
+-   Dmsg1(400, "Exit blocked=%s\n", dev->print_blocked());
++   Dmsg1(dbglvl, "Exit blocked=%s\n", dev->print_blocked());
+    dev->dunlock();
+    return stat;
+ }
+@@ -209,7 +219,7 @@
+    const int max_wait_time = 1 * 60;       /* wait 1 minute */
+    char ed1[50];
+-   Dmsg0(100, "Enter wait_for_device\n");
++   Dmsg0(dbglvl, "Enter wait_for_device\n");
+    P(device_release_mutex);
+    if (++retries % 5 == 0) {
+@@ -222,14 +232,14 @@
+    timeout.tv_nsec = tv.tv_usec * 1000;
+    timeout.tv_sec = tv.tv_sec + max_wait_time;
+-   Dmsg1(100, "JobId=%u going to wait for a device.\n", (uint32_t)jcr->JobId);
++   Dmsg0(dbglvl, "Going to wait for a device.\n");
+    /* Wait required time */
+    stat = pthread_cond_timedwait(&wait_device_release, &device_release_mutex, &timeout);
+-   Dmsg2(100, "JobId=%u wokeup from sleep on device stat=%d\n", (uint32_t)jcr->JobId, stat);
++   Dmsg1(dbglvl, "Wokeup from sleep on device stat=%d\n", stat);
+    V(device_release_mutex);
+-   Dmsg2(100, "JobId=%u return from wait_device ok=%d\n", (uint32_t)jcr->JobId, ok);
++   Dmsg1(dbglvl, "Return from wait_device ok=%d\n", ok);
+    return ok;
+ }
diff --git a/bacula/patches/2.2.x/2.2.5-lastwritten.patch b/bacula/patches/2.2.x/2.2.5-lastwritten.patch
new file mode 100644 (file)
index 0000000..c5373bc
--- /dev/null
@@ -0,0 +1,41 @@
+
+  This bug fixes the LastWritten field which was updated during
+  a restore (or a reading migration)
+  This fixes bug #982
+
+  This patch applies to Bacula version 2.2.5 (and previous versions),
+  and can be applied with the following:
+
+  cd <bacula-source>
+  patch -p0 <2.2.5-lastwritten.patch
+  ./configure (your options)
+  make
+  ...
+  make install
+
+
+
+Index: src/dird/catreq.c
+===================================================================
+--- src/dird/catreq.c  (révision 5789)
++++ src/dird/catreq.c  (copie de travail)
+@@ -266,6 +266,11 @@
+          }
+       }
+       Dmsg2(400, "Update media: BefVolJobs=%u After=%u\n", mr.VolJobs, sdmr.VolJobs);
++      /* Check if the volume has been written by the job, 
++       * and update the LastWritten field if needed */
++      if (mr.VolBlocks != sdmr.VolBlocks) {
++         mr.LastWritten = sdmr.LastWritten;
++      }
+       /* Copy updated values to original media record */
+       mr.VolJobs      = sdmr.VolJobs;
+       mr.VolFiles     = sdmr.VolFiles;
+@@ -274,7 +279,6 @@
+       mr.VolMounts    = sdmr.VolMounts;
+       mr.VolErrors    = sdmr.VolErrors;
+       mr.VolWrites    = sdmr.VolWrites;
+-      mr.LastWritten  = sdmr.LastWritten;
+       mr.Slot         = sdmr.Slot;
+       mr.InChanger    = sdmr.InChanger;
+       mr.VolReadTime  = sdmr.VolReadTime;
diff --git a/bacula/patches/2.2.x/2.2.5-nextvol.patch b/bacula/patches/2.2.x/2.2.5-nextvol.patch
new file mode 100644 (file)
index 0000000..27bf0d5
--- /dev/null
@@ -0,0 +1,29 @@
+
+  This bug fixes the warning message that prints each time an automatic
+  Volume name is created.  This fixes bug #979
+
+  This patch applies to Bacula version 2.2.5 (not to previous versions),
+  and can be applied with the following:
+
+  cd <bacula-source>
+  patch -p0 <2.2.5-newvol.patch
+  ./configure (your options)
+  make
+  ...
+  make install
+
+
+
+Index: src/dird/newvol.c
+===================================================================
+--- src/dird/newvol.c  (revision 5717)
++++ src/dird/newvol.c  (working copy)
+@@ -124,7 +124,7 @@
+    mr->VolumeName[0] = 0;
+    bstrncpy(name, pr->LabelFormat, sizeof(name));
+    ctx.value = 0;
+-   Mmsg(query, "SELECT MAX(MediaId) FROM Media,POOL WHERE Pool.PoolId=%s", 
++   Mmsg(query, "SELECT MAX(MediaId) FROM Media,Pool WHERE Pool.PoolId=%s", 
+         edit_int64(pr->PoolId, ed1));
+    if (!db_sql_query(jcr->db, query.c_str(), db_int64_handler, (void *)&ctx)) {
+       Jmsg(jcr, M_WARNING, 0, _("SQL failed, but ignored. ERR=%s\n"), db_strerror(jcr->db));
diff --git a/bacula/patches/2.2.x/2.2.5-postgresql-errors.patch b/bacula/patches/2.2.x/2.2.5-postgresql-errors.patch
new file mode 100644 (file)
index 0000000..fb52b80
--- /dev/null
@@ -0,0 +1,28 @@
+  After a sql error, the error message that is printed 
+  is incorrect and does not include the postgresql error message.  
+  It fixes #989
+
+  This patch applies to Bacula version 2.2.5 (and previous versions),
+  and can be applied with the following:
+
+  cd <bacula-source>
+  patch -p0 <2.2.5-postgresql-errors.patch
+  ./configure (your options)
+  make
+  ...
+  make install
+
+
+Index: src/cats/cats.h
+===================================================================
+--- src/cats/cats.h    (révision 5763)
++++ src/cats/cats.h    (copie de travail)
+@@ -498,7 +498,7 @@
+ #define sql_fetch_row(x)      my_postgresql_fetch_row(x)
+ #define sql_query(x, y)       my_postgresql_query((x), (y))
+ #define sql_close(x)          PQfinish((x)->db)
+-#define sql_strerror(x)       PQresultErrorMessage((x)->result)
++#define sql_strerror(x)       PQerrorMessage((x)->db)
+ #define sql_num_rows(x)       ((unsigned) PQntuples((x)->result))
+ #define sql_data_seek(x, i)   my_postgresql_data_seek((x), (i))
+ #define sql_affected_rows(x)  ((unsigned) atoi(PQcmdTuples((x)->result)))
diff --git a/bacula/patches/2.2.x/2.2.5-tray-monitor.patch b/bacula/patches/2.2.x/2.2.5-tray-monitor.patch
new file mode 100644 (file)
index 0000000..542aea7
--- /dev/null
@@ -0,0 +1,25 @@
+
+ This patch activates the Close button in the tray monitor window.
+ It fixes bug #986.
+
+ Apply it to Bacula version 2.2.5 with:
+
+ cd <bacula-source>
+ patch -p0 <2.2.5-tray-monitor.patch
+ make
+ ...
+ make install
+
+Index: src/tray-monitor/tray-monitor.c
+===================================================================
+--- src/tray-monitor/tray-monitor.c    (revision 5717)
++++ src/tray-monitor/tray-monitor.c    (working copy)
+@@ -478,7 +478,7 @@
+    gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, FALSE, 0);
+    button = new_image_button("gtk-close", _("Close"));
+-// g_signal_connect_swapped(G_OBJECT(button), "clicked", G_CALLBACK(gtk_widget_hide), G_OBJECT(window));
++   g_signal_connect_swapped(G_OBJECT(button), "clicked", G_CALLBACK(gtk_widget_hide), G_OBJECT(window));
+    gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, FALSE, 0);
+    gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
diff --git a/bacula/patches/2.2.x/2.2.5-verify-loop.patch b/bacula/patches/2.2.x/2.2.5-verify-loop.patch
new file mode 100644 (file)
index 0000000..9016cfe
--- /dev/null
@@ -0,0 +1,33 @@
+
+ This patch fixes bug #1003 where putting the message output from 
+ a Verify job into the catalog results in a recursive loop.  The problem
+ seems to show up only with postgresql (to be verified).
+
+ Apply it to version 2.2.5 (or probably any previous 2.2.x version) with
+
+ cd <bacula-source>
+ ./configure <your-options>  not necessary if already configured
+ patch -p0 <2.2.5-verify-loop.patch
+ make
+ ...
+ make install
+
+
+Index: src/dird/verify.c
+===================================================================
+--- src/dird/verify.c  (revision 5814)
++++ src/dird/verify.c  (working copy)
+@@ -767,11 +767,11 @@
+       return 1;
+    }
+    if (!jcr->fn_printed) {
+-      Jmsg(jcr, M_INFO, 0, _("\nThe following files are in the Catalog but not on %s:\n"),
++      Qmsg(jcr, M_INFO, 0, _("\nThe following files are in the Catalog but not on %s:\n"),
+        jcr->JobLevel == L_VERIFY_VOLUME_TO_CATALOG ? "the Volume(s)" : "disk");
+       jcr->fn_printed = true;
+    }
+-   Jmsg(jcr, M_INFO, 0, "      %s%s\n", row[0]?row[0]:"", row[1]?row[1]:"");
++   Qmsg(jcr, M_INFO, 0, "      %s%s\n", row[0]?row[0]:"", row[1]?row[1]:"");
+    return 0;
+ }
index 6aecf5331d04556447db675179070bada602856f..29a92541b6beb21c10635dd3663ab8d45f03b36d 100644 (file)
@@ -97,7 +97,7 @@ int find_next_volume_for_append(JCR *jcr, MEDIA_DBR *mr, int index,
                   prune_volumes(jcr, InChanger, mr);
                }
                ok = recycle_oldest_purged_volume(jcr, InChanger, mr);
-               if (!ok) {
+               if (!ok && create) {
                   Dmsg4(050, "after prune volumes_vol ok=%d index=%d InChanger=%d Vstat=%s\n",
                         ok, index, InChanger, mr->VolStatus);
                   /*
index bf3cae656635b2589d0a7e7fb91601c849d617a5..0e27fe47c20911ff1242f1523d7734ce6b242705 100644 (file)
@@ -1,12 +1,21 @@
               Technical notes on version 2.2
 
 General:
+02Dec07
+kes  This patch prevents the 'status dir' command from trying to use a scratch
+     volume and possibly moving it from one pool to another.  This patch fixes
+     bug #1019.
 30Nov07
 kes  Fix --archivedir addition to configure. Replace it with
      --with-archivedir in configure.in  This fixes the regression
      test builds.
 kes  This patch fixes bug #1012 where the job is canceled because
      of Max Run Time exceeded when the job has not yet started.
+29Nov07
+ebl  Apply Richard Mortimer patch that fixes #1016 when there are more than
+     one 'part' to write.  Instead of each part being stored on disk,
+     written to DVD, then deleted from disk, all parts are written to disk,
+     and only the last is written and deleted from disk.
 27Nov07
 kes  Correct typos in disk-changer.in
 25Nov07