elif test -f /etc/engarde-version
then
DISTNAME=engarde
-elif test "$ac_cv_cygwin" = yes
+elif test "$CYGWIN" = yes
then
DISTNAME=cygwin
AC_DEFINE(HAVE_CYGWIN)
ifelse([$4], , AC_MSG_ERROR([Library requirements ($2) not met; consider adjusting the PKG_CONFIG_PATH environment variable if your libraries are in a nonstandard prefix so pkg-config can find them.]), [$4])
fi
])
-
elif test -f /etc/engarde-version
then
DISTNAME=engarde
-elif test "$ac_cv_cygwin" = yes
+elif test "$CYGWIN" = yes
then
DISTNAME=cygwin
cat >>confdefs.h <<\_ACEOF
- Add counter variable test.
For 1.32:
-- Look at Cleaning tape in ua_label.c for media create/update
-- Fix get_storage_from_media_type (ua_restore) to use command line
- storage=
-- Document list nextvol and status output.
- Add GUI interface to manual
-- Add regression testing to the manual
-
+- Document that Volume pruning can delete last Full backup and
+ hence you will not have a valid backup.
+- Clarify the fact that having the Bacula cygwin1.dll loaded
+ is not the same as having cygwin installed.
+- Fix sparse file handeling so that it always reads a multiple
+ of 512. Currently, it subtracts 8 bytes (for faddr).
+- Separate Dir heartbeat in FD from the SD heartbeat.
For 1.33
+- When job rescheduled, status gives is waiting for Client Rufus
+ to connect to Storage File. Dir needs to inform SD that job
+ is rescheduled.
+- Fix get_storage_from_media_type (ua_restore) to use command line
+ storage=
- Enhance "update slots" to include a "scan" feature
scan 1; scan 1-5; scan 1,2,4 ... to update the catalog
- Allow a slot or range of slots on the label barcodes command.
- Figure out some way to ignore or get past checksum errors in
reading.
- The SD spooling file gets created even if it is not used.
+- Look at Cleaning tape in ua_label.c for media create/update
+- Add regression testing to the manual
+- End time: in job output of rescheduled job is time of first run.
+- Document list nextvol and status output.
FDPort = @fd_port@
Catalog = MyCatalog
Password = "@fd_password@" # password for FileDaemon
- File Retention = 30d # 30 days
- Job Retention = 180d # six months
+ File Retention = 30 days # 30 days
+ Job Retention = 6 months # six months
AutoPrune = yes # Prune expired Jobs/Files
}
Pool Type = Backup
Recycle = yes # Bacula can automatically recycle Volumes
AutoPrune = yes # Prune expired volumes
- Volume Retention = 365d # one year
+ Volume Retention = 365 days # one year
Accept Any Volume = yes # write on any volume in the pool
}
set_jcr_job_status(jcr, JS_Created);
jcr->jr.SchedTime = jcr->sched_time;
jcr->jr.StartTime = jcr->start_time;
+ jcr->jr.EndTime = 0; /* perhaps rescheduled, clear it */
jcr->jr.Type = jcr->JobType;
jcr->jr.Level = jcr->JobLevel;
jcr->jr.JobStatus = jcr->JobStatus;
/* Ensure that at least one server looks at the queue. */
stat = start_server(jq);
- if (stat == 0) {
- pthread_mutex_unlock(&jq->mutex);
- }
+ pthread_mutex_unlock(&jq->mutex);
Dmsg0(100, "Return jobq_add\n");
return stat;
}
jq->ready_jobs->prepend(item);
stat = start_server(jq);
- if (stat != 0) {
- return stat;
- }
+
pthread_mutex_unlock(&jq->mutex);
Dmsg0(100, "Return jobq_remove\n");
return stat;
if (jq->idle_workers > 0) {
Dmsg0(100, "Signal worker to wake up\n");
if ((stat = pthread_cond_signal(&jq->work)) != 0) {
- pthread_mutex_unlock(&jq->mutex);
return stat;
}
} else if (jq->num_workers < jq->max_workers) {
/* No idle threads so create a new one */
set_thread_concurrency(jq->max_workers + 1);
if ((stat = pthread_create(&id, &jq->attr, jobq_server, (void *)jq)) != 0) {
- pthread_mutex_unlock(&jq->mutex);
return stat;
}
- jq->num_workers++;
}
return stat;
}
if ((stat = pthread_mutex_lock(&jq->mutex)) != 0) {
return NULL;
}
+ jq->num_workers++;
for (;;) {
struct timeval tv;
if (!jq->ready_jobs->empty()) {
Dmsg0(100, "ready queue not empty start server\n");
if (start_server(jq) != 0) {
+ jq->num_workers--;
+ pthread_mutex_unlock(&jq->mutex);
return NULL;
}
}
jq->running_jobs->append(je);
Dmsg1(100, "Took jobid=%d from ready and appended to run\n", jcr->JobId);
if ((stat = pthread_mutex_unlock(&jq->mutex)) != 0) {
+ jq->num_workers--;
return NULL;
}
/* Call user's routine here */
jq->engine(je->jcr);
Dmsg1(100, "Back from user engine jobid=%d.\n", jcr->JobId);
if ((stat = pthread_mutex_lock(&jq->mutex)) != 0) {
+ jq->num_workers--;
free(je); /* release job entry */
return NULL;
}
* send_label_request() below
*/
if (is_cleaning_tape(ua, &mr, &pr)) {
- set_pool_dbr_defaults_in_media_dbr(&mr, &pr);
- if (db_create_media_record(ua->jcr, ua->db, &mr)) {
- bsendmsg(ua, _("Catalog record for cleaning tape \"%s\" successfully created.\n"),
- mr.VolumeName);
- } else {
- bsendmsg(ua, "Catalog error on cleaning tape: %s", db_strerror(ua->db));
+ if (media_record_exists) { /* we update it */
+ mr.VolBytes = 1;
+ if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
+ bsendmsg(ua, "%s", db_strerror(ua->db));
+ }
+ } else { /* create the media record */
+ set_pool_dbr_defaults_in_media_dbr(&mr, &pr);
+ if (db_create_media_record(ua->jcr, ua->db, &mr)) {
+ bsendmsg(ua, _("Catalog record for cleaning tape \"%s\" successfully created.\n"),
+ mr.VolumeName);
+ } else {
+ bsendmsg(ua, "Catalog error on cleaning tape: %s", db_strerror(ua->db));
+ }
}
- continue;
+ continue; /* done, go handle next volume */
}
bstrncpy(mr.MediaType, store->media_type, sizeof(mr.MediaType));
if (ua->jcr->store_bsock) {
continue;
}
switch (jcr->JobStatus) {
- case JS_Created:
- msg = _("is waiting execution");
- break;
- case JS_Running:
- msg = _("is running");
- break;
- case JS_Blocked:
- msg = _("is blocked");
- break;
- case JS_Terminated:
- msg = _("has terminated");
- break;
- case JS_ErrorTerminated:
- msg = _("has erred");
- break;
- case JS_Canceled:
- msg = _("has been canceled");
- break;
- case JS_WaitFD:
- msg = (char *) get_pool_memory(PM_FNAME);
- Mmsg(&msg, _("is waiting on Client %s"), jcr->client->hdr.name);
- pool_mem = TRUE;
- break;
- case JS_WaitSD:
- msg = (char *) get_pool_memory(PM_FNAME);
- Mmsg(&msg, _("is waiting on Storage %s"), jcr->store->hdr.name);
- pool_mem = TRUE;
- break;
- case JS_WaitStoreRes:
- msg = _("is waiting on max Storage jobs");
- break;
- case JS_WaitClientRes:
- msg = _("is waiting on max Client jobs");
- break;
- case JS_WaitJobRes:
- msg = _("is waiting on max Job jobs");
- break;
- case JS_WaitPriority:
- msg = _("is waiting for higher priority jobs to finish");
- break;
- case JS_WaitMaxJobs:
- msg = _("is waiting on max total jobs");
- break;
- case JS_WaitStartTime:
- msg = _("is waiting for its start time");
- break;
+ case JS_Created:
+ msg = _("is waiting execution");
+ break;
+ case JS_Running:
+ msg = _("is running");
+ break;
+ case JS_Blocked:
+ msg = _("is blocked");
+ break;
+ case JS_Terminated:
+ msg = _("has terminated");
+ break;
+ case JS_ErrorTerminated:
+ msg = _("has erred");
+ break;
+ case JS_Canceled:
+ msg = _("has been canceled");
+ break;
+ case JS_WaitFD:
+ msg = (char *) get_pool_memory(PM_FNAME);
+ Mmsg(&msg, _("is waiting on Client %s"), jcr->client->hdr.name);
+ pool_mem = TRUE;
+ break;
+ case JS_WaitSD:
+ msg = (char *) get_pool_memory(PM_FNAME);
+ Mmsg(&msg, _("is waiting on Storage %s"), jcr->store->hdr.name);
+ pool_mem = TRUE;
+ break;
+ case JS_WaitStoreRes:
+ msg = _("is waiting on max Storage jobs");
+ break;
+ case JS_WaitClientRes:
+ msg = _("is waiting on max Client jobs");
+ break;
+ case JS_WaitJobRes:
+ msg = _("is waiting on max Job jobs");
+ break;
+ case JS_WaitPriority:
+ msg = _("is waiting for higher priority jobs to finish");
+ break;
+ case JS_WaitMaxJobs:
+ msg = _("is waiting on max total jobs");
+ break;
+ case JS_WaitStartTime:
+ msg = _("is waiting for its start time");
+ break;
- default:
- msg = (char *) get_pool_memory(PM_FNAME);
- Mmsg(&msg, _("is in unknown state %c"), jcr->JobStatus);
- pool_mem = TRUE;
- break;
+ default:
+ msg = (char *) get_pool_memory(PM_FNAME);
+ Mmsg(&msg, _("is in unknown state %c"), jcr->JobStatus);
+ pool_mem = TRUE;
+ break;
}
+ /*
+ * Now report Storage daemon status code
+ */
switch (jcr->SDJobStatus) {
- case JS_WaitMount:
- if (pool_mem) {
- free_pool_memory(msg);
- pool_mem = FALSE;
- }
- msg = _("is waiting for a mount request");
- break;
- case JS_WaitMedia:
- if (pool_mem) {
- free_pool_memory(msg);
- pool_mem = FALSE;
- }
- msg = _("is waiting for an appendable Volume");
- break;
- case JS_WaitFD:
- if (!pool_mem) {
- msg = (char *) get_pool_memory(PM_FNAME);
- pool_mem = TRUE;
- }
- Mmsg(&msg, _("is waiting for Client %s to connect to Storage %s"),
- jcr->client->hdr.name, jcr->store->hdr.name);
- break;
-
+ case JS_WaitMount:
+ if (pool_mem) {
+ free_pool_memory(msg);
+ pool_mem = FALSE;
+ }
+ msg = _("is waiting for a mount request");
+ break;
+ case JS_WaitMedia:
+ if (pool_mem) {
+ free_pool_memory(msg);
+ pool_mem = FALSE;
+ }
+ msg = _("is waiting for an appendable Volume");
+ break;
+ case JS_WaitFD:
+ if (!pool_mem) {
+ msg = (char *) get_pool_memory(PM_FNAME);
+ pool_mem = TRUE;
+ }
+ Mmsg(&msg, _("is waiting for Client %s to connect to Storage %s"),
+ jcr->client->hdr.name, jcr->store->hdr.name);
+ break;
}
bsendmsg(ua, _("JobId %d Job %s %s.\n"), jcr->JobId, jcr->Job, msg);
if (pool_mem) {
if (ff_pkt->flags & FO_SPARSE) {
rbuf += SPARSE_FADDR_SIZE;
rsize -= SPARSE_FADDR_SIZE;
+#ifdef HAVE_FREEBSD_OS
+ /*
+ * To read FreeBSD partitions, the read size must be
+ * a multiple of 512.
+ */
+ rsize = (rsize/512) * 512;
+#endif
}
/*
jcr->hb_bsock = sd;
/* Hang reading the socket to the SD, and every time we get
- * a heartbeat, we simply send it on to the Director to
- * keep him alive.
+ * a heartbeat or we get a wait timeout (1 minute), we
+ * check to see if we need to send a heartbeat to the
+ * Directory.
*/
for ( ; !is_bnet_stop(sd); ) {
n = bnet_wait_data_intr(sd, WAIT_INTERVAL);
* a block device, we do a raw backup of it or if it is
* a fifo, we simply read it.
*/
+#ifdef HAVE_FREEBSD_OS
+ /*
+ * On FreeBSD, all block devices are character devices, so
+ * to be able to read a raw disk, we need the check for
+ * a character device.
+ * crw-r----- 1 root operator - 116, 0x00040002 Jun 9 19:32 /dev/ad0s3
+ * crw-r----- 1 root operator - 116, 0x00040002 Jun 9 19:32 /dev/rad0s3
+ */
+ if (top_level && (S_ISBLK(ff_pkt->statp.st_mode) || S_ISCHR(ff_pkt->statp.st_mode))) {
+#else
if (top_level && S_ISBLK(ff_pkt->statp.st_mode)) {
+#endif
ff_pkt->type = FT_RAW; /* raw partition */
} else if (top_level && S_ISFIFO(ff_pkt->statp.st_mode) &&
ff_pkt->flags & FO_READFIFO) {
struct timeval tv;
struct timezone tz;
struct timespec timeout;
+ JCR *ojcr;
/*
* Get JobId and permissions from Director
set_jcr_job_status(jcr, JS_ErrorTerminated);
return 0;
}
+ /*
+ * Since this job could be rescheduled, we
+ * check to see if we have it already. If so
+ * free the old jcr and use the new one.
+ */
+ ojcr = get_jcr_by_full_name(job);
+ if (ojcr && !ojcr->authenticated) {
+ Dmsg2(000, "Found ojcr=0x%x Job %s\n", (unsigned)ojcr, job);
+ free_jcr(ojcr);
+ }
jcr->JobId = JobId;
jcr->VolSessionId = newVolSessionId();
jcr->VolSessionTime = VolSessionTime;