+2003-10-01 Version 1.32a 03Oct03 Release
+04Oct03
+- Combine the code in ua_output and ua_status that searches
+ the run records.
+03Oct03
+- Fixed "list nextvol" to search for the correct pool in the
+ Schedule Run records.
+- Correct an error in is_block_zero. It found a false
+ match if the first 1016 bytes of a 32K buffer and
+ the last 248 bytes are zero. Broke the sparse option.
+01Oct03
+- More documentation.
+- Test if multiple mail addresses works. Yes.
+- Add debug Jmsg() to trigger if the file I/O packet is
+ not closed in the FD, i.e file descriptor leaks.
+- When error occurs reading label in mount.c, start from
+ the very top so that the retry count is in effect.
+- Zap the mode in soft links in testls.c for regression
+ testing.
+
2003-10-01 Version 1.32 30Sep03 Release
28Sep03
- Enhance manual faq, regression ...
- Release Notes for Bacula 1.33
+ Release Notes for Bacula 1.32a
- Bacula code: Total files = 259 Total lines = 77,740 (*.h *.c *.in)
+ Bacula code: Total files = 259 Total lines = 77,779 (*.h *.c *.in)
Major Changes this Release:
+- Implemented forward space file/block whenever possible
+ during restore. Restoring a small number of files is now
+ much faster.
+- There is a new option to restore that allows you
+ to restore files based on their Filename. You can
+ also specify a file to read which contains the list.
+- Added ClientRunBeforeJob and ClientRunAfterJob.
+- Implemented Include | and < in File daemon.
+- Automatic labeling of tape Volumes should work now.
+- Recycling has been completely restructured and should work.
+- Implemented full length time interval qualifiers (e.g
+ "5n is now "5 min" or "5 minutes". A modifier is now required!
+- Fixed gnome-console to compile with RH9 (Gnome 2.0)
+- Implemented "list nextvol job=xxx", which displays the
+ next volume to be used by job xxx. The Volume name to
+ be used is also added to the "status dir" output.
+- Lots of fixes with variable expansion and counter variables
+- Implemented a new Include/Exclude syntax.
+- While writing a tape, an end of file mark will be written
+ every 1Gb. This makes restores faster. If you want to
+ change this use "Maximum File Size" in the SD Device
+ resource.
Other Changes this Release:
+- Fixed sparse file bug.
+- A warning message is sent when a job starts that will be
+ blocked because the user did an "unmount".
+- Block checksum errors if any are printed in the job report.
+- Implemented a single routine to read_records. It also returns
+ a different record packet for each session. This means
+ that multiple simultaneous jobs should work.
+- Added SDConnectTimeout to FD.
+- Lots of doc enhancements
+- Fixed a PurgeOldestVolume bug (VolStatus not returned)
+- Don't crash if DB address record not specified.
+- Return VolStatus on find_next_volume.
+- Use alist for incexe name_list.
+- Use bget_dirmsg() everywhere possible when talking to FD.
+- Delete old semaphore job and workq job scheduling code.
+- edit_run_codes in one place (/lib) Add Job name
+- Update query.sql to find current backups correctly.
+- Correct ambiguous SQL statement for pruning.
+- Set heartbeat interval to zero by default.
+- Fix a possible race condition in stopping the
+ heartbeat thread.
+- Eliminate gnome2-console directory. Everything is in gnome-console
+- Enhanced "packet too big" message to indicate who sent it.
+- Corrected console prompt problem in non-readline versions.
+- Correct a number of variable expansion problems.
+- Added a number of new regression tests.
+- In an attempt to make configuration a bit less confusing, I've changed
+ the name of a number of variables. The old ones still work, but will
+ be phased out over time. FDAddress, FDPassword, SDAddress SDPassword,
+ SDDeviceName, and DBPassword.
+- A possible fix to the very intermittent SD crashes that Alex gets.
Items to note: !!!!!
+- Modifiers (sec, min, hour, day, ...) are now required on conf file
+ time interval specifications.
+- Duplicate names within the same conf resource are prohibited.
+- If you have used a prior BETA version of 1.32, please do
+ the following to cleanup any zero length spool files:
+
+ cd <working-directory-as-in-Bacula-conf>
+ rm -f *.spool.*
+
+ Please be sure there are no spaces between the asterisks
+ and the periods.
- Test connect timeouts.
For 1.33 Testing/Documentation:
+- Combine the 3 places that search run records for the next
+ job. Use find_job_pool() modified in ua_output.c
- Document to start higher priorty jobs before lower ones.
- suppress "Do not forget to mount the drive!!!" if error
- Document new records in Director. SDAddress SDDeviceName, SDPassword.
- Add counter variable test.
For 1.33
-- Eliminate orphaned jobs: dbcheck, normal pruning, delet job command.
+- Eliminate orphaned jobs: dbcheck, normal pruning, delete job command.
Hm. Well, there are the remaining orphaned job records:
| 105 | Llioness Save | 0000-00-00 00:00:00 | B | D | 0 | 0 | f |
/* ua_output.c */
void prtit(void *ctx, char *msg);
int complete_jcr_for_job(JCR *jcr, JOB *job, POOL *pool);
+RUN *find_next_run(JOB *job, time_t &runtime);
/* ua_server.c */
void bsendmsg(void *sock, char *fmt, ...);
/* Forward referenced functions */
static int do_list_cmd(UAContext *ua, char *cmd, e_list_type llist);
-static POOL *find_job_pool(JOB *job);
/*
* Turn auto display of console messages on/off
strcasecmp(ua->argk[i], _("nextvolume")) == 0) {
JOB *job;
JCR *jcr = ua->jcr;
+ POOL *pool;
+ RUN *run;
+ time_t runtime;
i = find_arg_with_value(ua, "job");
if (i <= 0) {
}
}
}
- if (!complete_jcr_for_job(jcr, job, find_job_pool(job))) {
+ run = find_next_run(job, runtime);
+ pool = run ? run->pool : NULL;
+ if (!complete_jcr_for_job(jcr, job, pool)) {
return 1;
}
return 1;
}
-static POOL *find_job_pool(JOB *job)
+/*
+ * For a given job, we examine all his run records
+ * to see if it is scheduled today or tomorrow.
+ */
+RUN *find_next_run(JOB *job, time_t &runtime)
{
- time_t now, runtime, tomorrow;
+ time_t now, tomorrow;
RUN *run;
SCHED *sched;
struct tm tm;
tm.tm_sec = 0;
runtime = mktime(&tm);
if (runtime > now) {
- return run->pool; /* return pool */
+ return run; /* found it, return run resource */
}
}
}
runtime = mktime(&tm);
Dmsg2(200, "truntime=%d now=%d\n", runtime, now);
if (runtime < tomorrow) {
- return run->pool; /* return pool */
+ return run; /* found it, return run resource */
}
}
} /* end for loop over runs */
*/
static void print_jobs_scheduled(UAContext *ua)
{
- time_t now, runtime, tomorrow;
+ time_t runtime;
RUN *run;
JOB *job;
- SCHED *sched;
- struct tm tm;
- int mday, wday, month, wpos, tmday, twday, tmonth, twpos, i, hour;
- int tod, tom;
- int found;
- int hdr_printed = FALSE;
+ bool hdr_printed = false;
int level;
Dmsg0(200, "enter find_runs()\n");
- now = time(NULL);
- localtime_r(&now, &tm);
- mday = tm.tm_mday - 1;
- wday = tm.tm_wday;
- month = tm.tm_mon;
- wpos = (tm.tm_mday - 1) / 7;
-
- tomorrow = now + 60 * 60 * 24;
- localtime_r(&tomorrow, &tm);
- tmday = tm.tm_mday - 1;
- twday = tm.tm_wday;
- tmonth = tm.tm_mon;
- twpos = (tm.tm_mday - 1) / 7;
-
/* Loop through all jobs */
LockRes();
for (job=NULL; (job=(JOB *)GetNextRes(R_JOB, (RES *)job)); ) {
level = job->level;
- sched = job->schedule;
- if (sched == NULL) { /* scheduled? */
- continue; /* no, skip this job */
+ run = find_next_run(job, runtime);
+ if (!run) {
+ continue;
}
- for (run=sched->run; run; run=run->next) {
- if (run->level) {
- level = run->level;
- }
- /*
- * Find runs in next 24 hours
- */
- tod = (bit_is_set(mday, run->mday) || bit_is_set(wday, run->wday)) &&
- bit_is_set(month, run->month) && bit_is_set(wpos, run->wpos);
-
- tom = (bit_is_set(tmday, run->mday) || bit_is_set(twday, run->wday)) &&
- bit_is_set(tmonth, run->month) && bit_is_set(wpos, run->wpos);
-
- Dmsg2(200, "tod=%d tom=%d\n", tod, tom);
- found = FALSE;
- if (tod) { /* Jobs scheduled today (next 24 hours) */
- /* find time (time_t) job is to be run */
- localtime_r(&now, &tm);
- hour = 0;
- for (i=tm.tm_hour; i < 24; i++) {
- if (bit_is_set(i, run->hour)) {
- tm.tm_hour = i;
- tm.tm_min = run->minute;
- tm.tm_sec = 0;
- runtime = mktime(&tm);
- if (runtime > now) {
- if (!hdr_printed) {
- hdr_printed = TRUE;
- prt_runhdr(ua);
- }
- prt_runtime(ua, job, level, runtime, run->pool);
- found = TRUE;
- break;
- }
- }
- }
- }
+ if (run->level) {
+ level = run->level;
+ }
+ if (!hdr_printed) {
+ hdr_printed = true;
+ prt_runhdr(ua);
+ }
+ prt_runtime(ua, job, level, runtime, run->pool);
-// Dmsg2(200, "runtime=%d now=%d\n", runtime, now);
- if (!found && tom) { /* look at jobs scheduled tomorrow */
- localtime_r(&tomorrow, &tm);
- hour = 0;
- for (i=0; i < 24; i++) {
- if (bit_is_set(i, run->hour)) {
- hour = i;
- break;
- }
- }
- tm.tm_hour = hour;
- tm.tm_min = run->minute;
- tm.tm_sec = 0;
- runtime = mktime(&tm);
- Dmsg2(200, "truntime=%d now=%d\n", runtime, now);
- if (runtime < tomorrow) {
- if (!hdr_printed) {
- hdr_printed = TRUE;
- prt_runhdr(ua);
- }
- prt_runtime(ua, job, level, runtime, run->pool);
- }
- }
- } /* end for loop over runs */
} /* end for loop over resources */
UnlockRes();
Dmsg0(200, "Leave find_runs()\n");
/* Return true of buffer has all zero bytes */
int is_buf_zero(char *buf, int len)
{
- uint64_t *ip = (uint64_t *)buf;
+ uint64_t *ip;
char *p;
int i, len64, done, rem;
+ if (buf[0] != 0) {
+ return 0;
+ }
+ ip = (uint64_t *)buf;
/* Optimize by checking uint64_t for zero */
- len64 = len >> sizeof(uint64_t);
+ len64 = len / sizeof(uint64_t);
for (i=0; i < len64; i++) {
if (ip[i] != 0) {
return 0;
}
}
- done = len64 << sizeof(uint64_t); /* bytes already checked */
+ done = len64 * sizeof(uint64_t); /* bytes already checked */
p = buf + done;
rem = len - done;
for (i = 0; i < rem; i++) {