+2003-xx-xx Version 1.31 Beta xxJun03
+- Very preliminary support for Gnome-2.0. Text does not yet work.
+- Correct buffer corruption in find_one.c with long directory names (Win32).
+- Make setting owner on directories M_ERROR rather than M_WARNING.
+- Fix printing of JobId in run listing for restore job.
+- Reduce heartbeat read check interval to every 10 seconds on Cygwin because
+ there is no working pthread_kill().
+- I finally designed a test for multiple simultaneous jobs,
+ and sure enough it broke when the jobs are split over multiple
+ volumes. Now fixed and working!
+- Eliminated a few "duplicate" error messages by testing for canceled.
+- Add ASSERT for device use count going negative.
+- Fix BlockNumber checking in stored/read.c (got first one wrong).
+- If socket is timed out, do a shutdown(fd,2) instead of close().
+- Fixed return status from SD to FD by setting JobStatus in append_end()
+- Add arrays to Environment variables. Elements separated by |.
+- Implement Reschedule On Error, Reschedule Interval, Reschedule Times.
+- Add a new pool PM_NAME -- gets a name length buffer.
+- Implement fast cancel of FD blocked on writing to SD by using
+ pthread_cancel(). Turned off on Cygwin due to bug.
+- Add code to handle EAGAIN in writing (probably not necessary). Use
+ select().
+- Eliminate size_t from pool control buffers.
+- Complete Counter resource.
+- Complete LabelFormat (except for WrapCounter) plus counter
+ inrementation.
+- This needs a database change to eliminate PoolId from counters.
+- Made a more compact format for the document index.
+- Add Phil's checkhost to examples directory (thanks Phil).
+- Implement generalized LabelFormat (documentation to come).
+- Implement Counter resource.
+- Cleanup examples/kernsconfig
+- Implement restore to a specific date.
+- Fixed a but in automatic labeling (and use durations expiring) analysed
+ and reported by Rob Proffitt (thanks!).
+- Cleaned up a few Cygwin compile problems.
+- Made a 10Jun03 release (it is in production here)
+- Finally took the big plunge and fixed restoration of links and other
+ files that have been changed between the backup and restore. Basically
+ if the file exists, it is deleted, then re-created.
+- Purge only Volumes marked Append, Full, Used, or Error.
+- Allow pruning of volumes marked Append, in addition to Full and Used.
+
+
2003-06-10 Version 1.31 Beta 10Jun03
- Eliminated all plain email addresses and replaced them with " at " in
place of @ to reduce havesting by spammers. Doc + Web Site.
Release Notes for Bacula 1.31
- Bacula code: Total files = 250 Total lines = 74,359 (*.h *.c *.in)
+ Bacula code: Total files = 250 Total lines = 74,376 (*.h *.c *.in)
Major Changes this Release:
- The database format has changed. Please see below.
- Added readline to depkgs (removed from depkgs1) and fixed configuration if
it is not installed in your system libraries.
- Implemented generalized tape label formats including counter variables.
-- Implement multiple simultaneous jobs.
+- Multiple simultaneous jobs now work.
+- Implemented tape block rejection, which means that restores with
+ several incremental backups will run orders of magnitude faster.
Other Changes this Release:
+- During a normal restore (replace = yes), any existing file is deleted
+ and the restored file is then created. This corrects links and other
+ wierd files that changed between the backup and the restore.
- Preliminary support for BSDi.
- Use smtp instead of mail to send the traceback message.
- Fixed a race condition in the "list" command while a backup is
- Beginning of support for SSL encryption.
- Beggining of support for Base level backups.
- Improvements to gnome-console.
-- Prune certain orphaned jobs (no files saved, no Volume used).
+- Prune orphaned jobs (no files saved, no Volume used).
- Added non-fatal errors to Job reports.
- Eliminate need for SubsysDirectory in each daemon -- please remove
these records from your .conf files.
- Better handling of errors with autochangers during restore.
- Better cancellation of jobs in Storage daemon (doesn't try
to cleanup twice).
+- Better cancellation of File daemon (except on Cygwin systems).
- SD error messages such as autochanger errors are now properly
directed back to Console -- previously some were lost.
-- A Storage daemon crash on FreeBSD systems (due to an improper FreeBSD
- pthreads implementation -- IMO) is fixed.
+- A Storage daemon crash on FreeBSD systems (due to a different FreeBSD
+ pthreads implementation) is fixed.
- Better Job termination report particularly for Verify and Restore jobs.
- Update Verify VolumeToCatalog to use new BSR records.
- Fixed list last 20 jobs in restore command (previously reported any
20 jobs).
- Gnome command line history works better.
- Better messages if a job is upgraded from Diff or Inc to Full.
+- Replaced FileSet MD5 with date created -- more aestetic and readable.
+- Fixed a FD crash on long directory names (Win32 specific).
*/
/*
- Copyright (C) 2002 Kern Sibbald and John Walker
+ Copyright (C) 2000-2003 Kern Sibbald and John Walker
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
*/
-
#include "bacula.h"
#include "stored.h"
#include <fnmatch.h>
/* Forward references */
-static int match_volume(BSR *bsr, BSR_VOLUME *volume, VOLUME_LABEL *volrec, int done);
-static int match_sesstime(BSR *bsr, BSR_SESSTIME *sesstime, DEV_RECORD *rec, int done);
-static int match_sessid(BSR *bsr, BSR_SESSID *sessid, DEV_RECORD *rec, int done);
-static int match_client(BSR *bsr, BSR_CLIENT *client, SESSION_LABEL *sessrec, int done);
-static int match_job(BSR *bsr, BSR_JOB *job, SESSION_LABEL *sessrec, int done);
-static int match_job_type(BSR *bsr, BSR_JOBTYPE *job_type, SESSION_LABEL *sessrec, int done);
-static int match_job_level(BSR *bsr, BSR_JOBLEVEL *job_level, SESSION_LABEL *sessrec, int done);
-static int match_jobid(BSR *bsr, BSR_JOBID *jobid, SESSION_LABEL *sessrec, int done);
-static int match_findex(BSR *bsr, BSR_FINDEX *findex, DEV_RECORD *rec, int done);
-static int match_volfile(BSR *bsr, BSR_VOLFILE *volfile, DEV_RECORD *rec, int done);
-static int match_stream(BSR *bsr, BSR_STREAM *stream, DEV_RECORD *rec, int done);
-static int match_all(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec, SESSION_LABEL *sessrec, int done);
+static int match_volume(BSR *bsr, BSR_VOLUME *volume, VOLUME_LABEL *volrec, bool done);
+static int match_sesstime(BSR *bsr, BSR_SESSTIME *sesstime, DEV_RECORD *rec, bool done);
+static int match_sessid(BSR *bsr, BSR_SESSID *sessid, DEV_RECORD *rec);
+static int match_client(BSR *bsr, BSR_CLIENT *client, SESSION_LABEL *sessrec, bool done);
+static int match_job(BSR *bsr, BSR_JOB *job, SESSION_LABEL *sessrec, bool done);
+static int match_job_type(BSR *bsr, BSR_JOBTYPE *job_type, SESSION_LABEL *sessrec, bool done);
+static int match_job_level(BSR *bsr, BSR_JOBLEVEL *job_level, SESSION_LABEL *sessrec, bool done);
+static int match_jobid(BSR *bsr, BSR_JOBID *jobid, SESSION_LABEL *sessrec, bool done);
+static int match_findex(BSR *bsr, BSR_FINDEX *findex, DEV_RECORD *rec, bool done);
+static int match_volfile(BSR *bsr, BSR_VOLFILE *volfile, DEV_RECORD *rec, bool done);
+static int match_stream(BSR *bsr, BSR_STREAM *stream, DEV_RECORD *rec, bool done);
+static int match_all(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec, SESSION_LABEL *sessrec, bool done);
+static int match_block_sesstime(BSR *bsr, BSR_SESSTIME *sesstime, DEV_BLOCK *block);
+static int match_block_sessid(BSR *bsr, BSR_SESSID *sessid, DEV_BLOCK *block);
+
+/*********************************************************************
+ *
+ * If possible, position the archive device (tape) to read the
+ * next block.
+ */
+void position_bsr_block(BSR *bsr, DEV_BLOCK *block)
+{
+ /* To be implemented */
+}
+
+/*********************************************************************
+ *
+ * Do fast block rejection based on bootstrap records.
+ * use_fast_rejection will be set if we have VolSessionId and VolSessTime
+ * in each record. When BlockVer is >= 2, we have those in the block header
+ * so can do fast rejection.
+ *
+ * returns: 1 if block may contain valid records
+ * 0 if block may be skipped (i.e. it contains no records of
+ * that can match the bsr).
+ *
+ */
+int match_bsr_block(BSR *bsr, DEV_BLOCK *block)
+{
+ if (!bsr || !bsr->use_fast_rejection || (block->BlockVer < 2)) {
+ return 1; /* cannot fast reject */
+ }
+
+ if (match_block_sesstime(bsr, bsr->sesstime, block)) {
+ return 1;
+ }
+ return match_block_sessid(bsr, bsr->sessid, block);
+}
+
+static int match_block_sesstime(BSR *bsr, BSR_SESSTIME *sesstime, DEV_BLOCK *block)
+{
+ if (!sesstime) {
+ return 1; /* no specification matches all */
+ }
+ if (sesstime->sesstime == block->VolSessionTime) {
+ return 1;
+ }
+ if (sesstime->next) {
+ return match_block_sesstime(bsr, sesstime->next, block);
+ }
+ return 0;
+}
+
+static int match_block_sessid(BSR *bsr, BSR_SESSID *sessid, DEV_BLOCK *block)
+{
+ if (!sessid) {
+ return 1; /* no specification matches all */
+ }
+ if (sessid->sessid <= block->VolSessionId && sessid->sessid2 >= block->VolSessionId) {
+ return 1;
+ }
+ if (sessid->next) {
+ return match_block_sessid(bsr, sessid->next, block);
+ }
+ return 0;
+}
+
/*********************************************************************
*
int stat;
if (bsr) {
- stat = match_all(bsr, rec, volrec, sessrec, 1);
+ stat = match_all(bsr, rec, volrec, sessrec, true);
} else {
stat = 0;
}
* returns -1 no additional matches possible
*/
static int match_all(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec,
- SESSION_LABEL *sessrec, int done)
+ SESSION_LABEL *sessrec, bool done)
{
if (bsr->done) {
goto no_match;
}
if (bsr->count && bsr->count <= bsr->found) {
- bsr->done = 1;
+ bsr->done = true;
goto no_match;
}
if (!match_volume(bsr, bsr->volume, volrec, 1)) {
}
/* NOTE!! This test MUST come after the sesstime test */
- if (!match_sessid(bsr, bsr->sessid, rec, 1)) {
+ if (!match_sessid(bsr, bsr->sessid, rec)) {
goto no_match;
}
return 0;
}
-static int match_volume(BSR *bsr, BSR_VOLUME *volume, VOLUME_LABEL *volrec, int done)
+static int match_volume(BSR *bsr, BSR_VOLUME *volume, VOLUME_LABEL *volrec, bool done)
{
if (!volume) {
return 0; /* Volume must match */
return 0;
}
-static int match_client(BSR *bsr, BSR_CLIENT *client, SESSION_LABEL *sessrec, int done)
+static int match_client(BSR *bsr, BSR_CLIENT *client, SESSION_LABEL *sessrec, bool done)
{
if (!client) {
return 1; /* no specification matches all */
return 0;
}
-static int match_job(BSR *bsr, BSR_JOB *job, SESSION_LABEL *sessrec, int done)
+static int match_job(BSR *bsr, BSR_JOB *job, SESSION_LABEL *sessrec, bool done)
{
if (!job) {
return 1; /* no specification matches all */
return 0;
}
-static int match_job_type(BSR *bsr, BSR_JOBTYPE *job_type, SESSION_LABEL *sessrec, int done)
+static int match_job_type(BSR *bsr, BSR_JOBTYPE *job_type, SESSION_LABEL *sessrec, bool done)
{
if (!job_type) {
return 1; /* no specification matches all */
return 0;
}
-static int match_job_level(BSR *bsr, BSR_JOBLEVEL *job_level, SESSION_LABEL *sessrec, int done)
+static int match_job_level(BSR *bsr, BSR_JOBLEVEL *job_level, SESSION_LABEL *sessrec, bool done)
{
if (!job_level) {
return 1; /* no specification matches all */
return 0;
}
-static int match_jobid(BSR *bsr, BSR_JOBID *jobid, SESSION_LABEL *sessrec, int done)
+static int match_jobid(BSR *bsr, BSR_JOBID *jobid, SESSION_LABEL *sessrec, bool done)
{
if (!jobid) {
return 1; /* no specification matches all */
return 0;
}
-static int match_volfile(BSR *bsr, BSR_VOLFILE *volfile, DEV_RECORD *rec, int done)
+static int match_volfile(BSR *bsr, BSR_VOLFILE *volfile, DEV_RECORD *rec, bool done)
{
if (!volfile) {
return 1; /* no specification matches all */
}
/* Once we get past last efile, we are done */
if (rec->File > volfile->efile) {
- volfile->done = 1; /* set local done */
+ volfile->done = true; /* set local done */
}
if (volfile->next) {
return match_volfile(bsr, volfile->next, rec, volfile->done && done);
/* If we are done and all prior matches are done, this bsr is finished */
if (volfile->done && done) {
- bsr->done = 1;
+ bsr->done = true;
}
return 0;
}
-static int match_stream(BSR *bsr, BSR_STREAM *stream, DEV_RECORD *rec, int done)
+static int match_stream(BSR *bsr, BSR_STREAM *stream, DEV_RECORD *rec, bool done)
{
if (!stream) {
return 1; /* no specification matches all */
return 0;
}
-static int match_sesstime(BSR *bsr, BSR_SESSTIME *sesstime, DEV_RECORD *rec, int done)
+static int match_sesstime(BSR *bsr, BSR_SESSTIME *sesstime, DEV_RECORD *rec, bool done)
{
if (!sesstime) {
return 1; /* no specification matches all */
return 1;
}
if (rec->VolSessionTime > sesstime->sesstime) {
- sesstime->done = 1;
+ sesstime->done = true;
}
if (sesstime->next) {
return match_sesstime(bsr, sesstime->next, rec, sesstime->done && done);
}
if (sesstime->done && done) {
- bsr->done = 1;
+ bsr->done = true;
}
return 0;
}
-static int match_sessid(BSR *bsr, BSR_SESSID *sessid, DEV_RECORD *rec, int done)
+static int match_sessid(BSR *bsr, BSR_SESSID *sessid, DEV_RECORD *rec)
{
if (!sessid) {
return 1; /* no specification matches all */
return 1;
}
if (sessid->next) {
- return match_sessid(bsr, sessid->next, rec, sessid->done && done);
- }
- if (sessid->done && done) {
- bsr->done = 1;
+ return match_sessid(bsr, sessid->next, rec);
}
return 0;
}
-static int match_findex(BSR *bsr, BSR_FINDEX *findex, DEV_RECORD *rec, int done)
+static int match_findex(BSR *bsr, BSR_FINDEX *findex, DEV_RECORD *rec, bool done)
{
if (!findex) {
return 1; /* no specification matches all */
return 1;
}
if (rec->FileIndex > findex->findex2) {
- findex->done = 1;
+ findex->done = true;
}
if (findex->next) {
return match_findex(bsr, findex->next, rec, findex->done && done);
}
if (findex->done && done) {
- bsr->done = 1;
+ bsr->done = true;
}
return 0;
}