/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
The main author of Bacula is Kern Sibbald, with contributions from
many others, a complete list can be found in the file AUTHORS.
* Open database
*/
Dmsg0(100, "Open database\n");
- jcr->db=db_init_database(jcr, jcr->catalog->db_name, jcr->catalog->db_user,
- jcr->catalog->db_password, jcr->catalog->db_address,
- jcr->catalog->db_port, jcr->catalog->db_socket,
- jcr->catalog->mult_db_connections);
+ jcr->db=db_init(jcr, jcr->catalog->db_driver, jcr->catalog->db_name,
+ jcr->catalog->db_user,
+ jcr->catalog->db_password, jcr->catalog->db_address,
+ jcr->catalog->db_port, jcr->catalog->db_socket,
+ jcr->catalog->mult_db_connections);
if (!jcr->db || !db_open_database(jcr, jcr->db)) {
Jmsg(jcr, M_FATAL, 0, _("Could not open database \"%s\".\n"),
jcr->catalog->db_name);
pm_strcpy(jcr->pool_source, _("unknown source"));
}
Dmsg2(500, "pool=%s (From %s)\n", jcr->pool->name(), jcr->pool_source);
- if (jcr->JobType == JT_MIGRATE) {
+ if (jcr->JobType == JT_MIGRATE || jcr->JobType == JT_COPY) {
if (!jcr->rpool_source) {
jcr->rpool_source = get_pool_memory(PM_MESSAGE);
pm_strcpy(jcr->rpool_source, _("unknown source"));
admin_cleanup(jcr, JS_ErrorTerminated);
}
break;
+ case JT_COPY:
case JT_MIGRATE:
if (!do_migration_init(jcr)) {
migration_cleanup(jcr, JS_ErrorTerminated);
{
JCR *jcr = (JCR *)arg;
- jcr->my_thread_id = pthread_self();
- pthread_detach(jcr->my_thread_id);
+ pthread_detach(pthread_self());
Dsm_check(1);
Dmsg0(200, "=====Start Job=========\n");
admin_cleanup(jcr, JS_ErrorTerminated);
}
break;
- case JT_MIGRATE:
case JT_COPY:
- case JT_ARCHIVE:
+ case JT_MIGRATE:
if (do_migration(jcr)) {
do_autoprune(jcr);
} else {
return true;
}
+void cancel_storage_daemon_job(JCR *jcr)
+{
+ UAContext *ua = new_ua_context(jcr);
+ JCR *control_jcr = new_control_jcr("*JobCancel*", JT_SYSTEM);
+ BSOCK *sd;
+
+ ua->jcr = control_jcr;
+ if (jcr->store_bsock) {
+ if (!ua->jcr->wstorage) {
+ if (jcr->rstorage) {
+ copy_wstorage(ua->jcr, jcr->rstorage, _("Job resource"));
+ } else {
+ copy_wstorage(ua->jcr, jcr->wstorage, _("Job resource"));
+ }
+ } else {
+ USTORE store;
+ if (jcr->rstorage) {
+ store.store = jcr->rstore;
+ } else {
+ store.store = jcr->wstore;
+ }
+ set_wstorage(ua->jcr, &store);
+ }
+
+ if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
+ goto bail_out;
+ }
+ Dmsg0(200, "Connected to storage daemon\n");
+ sd = ua->jcr->store_bsock;
+ sd->fsend("cancel Job=%s\n", jcr->Job);
+ while (sd->recv() >= 0) {
+ }
+ sd->signal(BNET_TERMINATE);
+ sd->close();
+ ua->jcr->store_bsock = NULL;
+ }
+bail_out:
+ free_jcr(control_jcr);
+ free_ua_context(ua);
+}
static void job_monitor_destructor(watchdog_t *self)
{
*/
static bool job_check_maxruntime(JCR *control_jcr, JCR *jcr)
{
- if (jcr->job->MaxRunTime == 0 || job_canceled(jcr)) {
+ if (jcr->job->MaxRunTime == 0 || job_canceled(jcr) || jcr->JobStatus == JS_Created) {
return false;
}
if ((watchdog_time - jcr->start_time) < jcr->job->MaxRunTime) {
while (!db_get_pool_record(jcr, jcr->db, &pr)) { /* get by Name */
/* Try to create the pool */
if (create_pool(jcr, jcr->db, jcr->pool, POOL_OP_CREATE) < 0) {
- Jmsg(jcr, M_FATAL, 0, _("Pool %s not in database. %s"), pr.Name,
+ Jmsg(jcr, M_FATAL, 0, _("Pool \"%s\" not in database. ERR=%s"), pr.Name,
db_strerror(jcr->db));
return 0;
} else {
- Jmsg(jcr, M_INFO, 0, _("Pool %s created in database.\n"), pr.Name);
+ Jmsg(jcr, M_INFO, 0, _("Created database record for Pool \"%s\".\n"), pr.Name);
}
}
return pr.PoolId;
}
+/*
+ * Check for duplicate jobs.
+ * Returns: true if current job should continue
+ * false if current job should terminate
+ */
+bool allow_duplicate_job(JCR *jcr)
+{
+ JOB *job = jcr->job;
+ JCR *djcr; /* possible duplicate */
+
+ if (job->AllowDuplicateJobs) {
+ return true;
+ }
+ if (!job->AllowHigherDuplicates) {
+ foreach_jcr(djcr) {
+ if (strcmp(job->name(), djcr->job->name()) == 0) {
+ bool cancel_queued = false;
+ if (job->DuplicateJobProximity > 0) {
+ time_t now = time(NULL);
+ if ((now - djcr->start_time) > job->DuplicateJobProximity) {
+ continue; /* not really a duplicate */
+ }
+ }
+ /* Cancel */
+ if (!(job->CancelQueuedDuplicates || job->CancelRunningDuplicates)) {
+ /* Zap current job */
+ Jmsg(jcr, M_FATAL, 0, _("Duplicate job not allowed.\n"));
+ return false;
+ }
+ /* If CancelQueuedDuplicates is set do so only if job is queued */
+ if (job->CancelQueuedDuplicates) {
+ switch (djcr->JobStatus) {
+ case JS_Created:
+ case JS_WaitJobRes:
+ case JS_WaitClientRes:
+ case JS_WaitStoreRes:
+ case JS_WaitPriority:
+ case JS_WaitMaxJobs:
+ case JS_WaitStartTime:
+ cancel_queued = true;
+ break;
+ default:
+ break;
+ }
+ }
+ if (cancel_queued || job->CancelRunningDuplicates) {
+ UAContext *ua = new_ua_context(djcr);
+ char ec1[50];
+ Jmsg(jcr, M_INFO, 0, _("Cancelling duplicate JobId=%s.\n"),
+ edit_uint64(djcr->JobId, ec1));
+ ua->jcr = djcr;
+ cancel_job(ua, djcr);
+ free_ua_context(ua);
+ Dmsg2(800, "Have cancelled JCR %p Job=%d\n", djcr, djcr->JobId);
+ }
+ }
+ }
+ }
+ return true;
+}
+
void apply_pool_overrides(JCR *jcr)
{
+ bool pool_override = false;
+
if (jcr->run_pool_override) {
pm_strcpy(jcr->pool_source, _("Run pool override"));
}
case L_FULL:
if (jcr->full_pool) {
jcr->pool = jcr->full_pool;
+ pool_override = true;
if (jcr->run_full_pool_override) {
pm_strcpy(jcr->pool_source, _("Run FullPool override"));
} else {
case L_INCREMENTAL:
if (jcr->inc_pool) {
jcr->pool = jcr->inc_pool;
+ pool_override = true;
if (jcr->run_inc_pool_override) {
pm_strcpy(jcr->pool_source, _("Run IncPool override"));
} else {
case L_DIFFERENTIAL:
if (jcr->diff_pool) {
jcr->pool = jcr->diff_pool;
+ pool_override = true;
if (jcr->run_diff_pool_override) {
pm_strcpy(jcr->pool_source, _("Run DiffPool override"));
} else {
}
break;
}
+ /* Update catalog if pool overridden */
+ if (pool_override && jcr->pool->catalog) {
+ jcr->catalog = jcr->pool->catalog;
+ pm_strcpy(jcr->catalog_source, _("Pool resource"));
+ }
}
* Takes base_name and appends (unique) current
* date and time to form unique job name.
*
+ * Note, the seconds are actually a sequence number. This
+ * permits us to start a maximum fo 59 unique jobs a second, which
+ * should be sufficient.
+ *
* Returns: unique job name in jcr->Job
* date/time in jcr->start_time
*/
/* Job start mutex */
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static time_t last_start_time = 0;
+ static int seq = 0;
time_t now;
struct tm tm;
char dt[MAX_TIME_LENGTH];
*/
P(mutex); /* lock creation of jobs */
now = time(NULL);
- while (now == last_start_time) {
- bmicrosleep(0, 500000);
- now = time(NULL);
+ seq++;
+ if (seq > 59) { /* wrap as if it is seconds */
+ seq = 0;
+ while (now == last_start_time) {
+ bmicrosleep(0, 500000);
+ now = time(NULL);
+ }
}
last_start_time = now;
V(mutex); /* allow creation of jobs */
/* Form Unique JobName */
(void)localtime_r(&now, &tm);
/* Use only characters that are permitted in Windows filenames */
- strftime(dt, sizeof(dt), "%Y-%m-%d_%H.%M.%S", &tm);
+ strftime(dt, sizeof(dt), "%Y-%m-%d_%H.%M", &tm);
bstrncpy(name, base_name, sizeof(name));
name[sizeof(name)-22] = 0; /* truncate if too long */
- bsnprintf(jcr->Job, sizeof(jcr->Job), "%s.%s", name, dt); /* add date & time */
+ bsnprintf(jcr->Job, sizeof(jcr->Job), "%s.%s.%02d", name, dt, seq); /* add date & time */
/* Convert spaces into underscores */
for (p=jcr->Job; *p; p++) {
if (*p == ' ') {
free_pool_memory(jcr->pool_source);
jcr->pool_source = NULL;
}
+ if (jcr->catalog_source) {
+ free_pool_memory(jcr->catalog_source);
+ jcr->catalog_source = NULL;
+ }
if (jcr->rpool_source) {
free_pool_memory(jcr->rpool_source);
jcr->rpool_source = NULL;
free_rwstorage(jcr);
jcr->job_end_push.destroy();
+
+ if (jcr->JobId != 0)
+ write_state_file(director->working_directory, "bacula-dir", get_first_port_host_order(director->DIRaddrs));
+
Dmsg0(200, "End dird free_jcr\n");
}
{
jcr->job = job;
jcr->JobType = job->JobType;
+ jcr->JobStatus = JS_Created;
switch (jcr->JobType) {
case JT_ADMIN:
case JT_RESTORE:
jcr->JobLevel = L_NONE;
break;
+ case JT_COPY:
case JT_MIGRATE:
if (!jcr->rpool_source) {
jcr->rpool_source = get_pool_memory(PM_MESSAGE);
jcr->pool_source = get_pool_memory(PM_MESSAGE);
pm_strcpy(jcr->pool_source, _("unknown source"));
}
+ if (!jcr->catalog_source) {
+ jcr->catalog_source = get_pool_memory(PM_MESSAGE);
+ pm_strcpy(jcr->catalog_source, _("unknown source"));
+ }
jcr->JobPriority = job->Priority;
/* Copy storage definitions -- deleted in dir_free_jcr above */
jcr->full_pool = job->full_pool;
jcr->inc_pool = job->inc_pool;
jcr->diff_pool = job->diff_pool;
- jcr->catalog = job->client->catalog;
+ if (job->pool->catalog) {
+ jcr->catalog = job->pool->catalog;
+ pm_strcpy(jcr->catalog_source, _("Pool resource"));
+ } else {
+ jcr->catalog = job->client->catalog;
+ pm_strcpy(jcr->catalog_source, _("Client resource"));
+ }
jcr->fileset = job->fileset;
jcr->messages = job->messages;
jcr->spool_data = job->spool_data;
+ jcr->spool_size = job->spool_size;
jcr->write_part_after_job = job->write_part_after_job;
+ jcr->accurate = job->accurate;
if (jcr->RestoreBootstrap) {
free(jcr->RestoreBootstrap);
jcr->RestoreBootstrap = NULL;
switch(jcr->JobType) {
case JT_RESTORE:
case JT_VERIFY:
+ case JT_COPY:
case JT_MIGRATE:
copy_rstorage(jcr, storage, where);
break;
}
-/* Set storage override */
+/* Set storage override. Releases any previous storage definition */
void set_rwstorage(JCR *jcr, USTORE *store)
{
if (!store) {
switch(jcr->JobType) {
case JT_RESTORE:
case JT_VERIFY:
+ case JT_COPY:
case JT_MIGRATE:
set_rstorage(jcr, store);
break;
}
-/* Set storage override */
+/* Set storage override. Remove all previous storage */
void set_rstorage(JCR *jcr, USTORE *store)
{
STORE *storage;
if (!store->store) {
return;
}
+ if (jcr->rstorage) {
+ free_rstorage(jcr);
+ }
if (!jcr->rstorage) {
jcr->rstorage = New(alist(10, not_owned_by_alist));
}
}
-/* Set storage override */
+/* Set storage override. Remove all previous storage */
void set_wstorage(JCR *jcr, USTORE *store)
{
STORE *storage;
if (!store->store) {
return;
}
+ if (jcr->wstorage) {
+ free_wstorage(jcr);
+ }
if (!jcr->wstorage) {
jcr->wstorage = New(alist(10, not_owned_by_alist));
}
UAContext *ua;
memset(&rx, 0, sizeof(rx));
rx.bsr = new_bsr();
- rx.JobIds = "";
+ rx.JobIds = (char *)"";
rx.bsr->JobId = jcr->previous_jr.JobId;
ua = new_ua_context(jcr);
complete_bsr(ua, rx.bsr);
jcr->needs_sd = true;
return true;
}
+
+bool run_console_command(JCR *jcr, const char *cmd){
+ UAContext *ua;
+ bool ok;
+
+ ua = new_ua_context(jcr);
+ Mmsg(ua->cmd, "%s", cmd);
+ Dmsg1(100, "Console command: %s\n", ua->cmd);
+ parse_ua_args(ua);
+ ok= do_a_command(ua);
+ free_ua_context(ua);
+ return ok;
+}