X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fdird%2Fmigrate.c;h=7657c8cd27f19fbe7ea65f504631753b32fe131b;hb=3f8a3a045ea058657030f588a10f786449d00e0d;hp=4bc1d60678d94554331ef00a0acd6844d6f6814c;hpb=57ef83037a3940466208e3f11cdd112daca6a26e;p=bacula%2Fbacula diff --git a/bacula/src/dird/migrate.c b/bacula/src/dird/migrate.c index 4bc1d60678..7657c8cd27 100644 --- a/bacula/src/dird/migrate.c +++ b/bacula/src/dird/migrate.c @@ -40,6 +40,10 @@ static char OKbootstrap[] = "3000 OK bootstrap\n"; static bool get_job_to_migrate(JCR *jcr); +struct idpkt; +static bool regex_find_jobids(JCR *jcr, idpkt *ids, const char *query1, + const char *query2, const char *type); +static void start_migration_job(JCR *jcr); /* * Called here before the job is run to do the job @@ -49,6 +53,7 @@ bool do_migration_init(JCR *jcr) { POOL_DBR pr; + /* If we find a job to migrate it is previous_jr.JobId */ if (!get_job_to_migrate(jcr)) { return false; } @@ -122,15 +127,16 @@ bool do_migration(JCR *jcr) POOL *pool; char ed1[100]; BSOCK *sd; - JOB *job, *tjob; - JCR *tjcr; + JOB *job, *prev_job; + JCR *prev_jcr; if (jcr->previous_jr.JobId == 0) { - jcr->JobStatus = JS_Terminated; + set_jcr_job_status(jcr, JS_Terminated); migration_cleanup(jcr, jcr->JobStatus); return true; /* no work */ } - Dmsg4(000, "Target: Name=%s JobId=%d Type=%c Level=%c\n", + + Dmsg4(000, "Previous:: Name=%s JobId=%d Type=%c Level=%c\n", jcr->previous_jr.Name, jcr->previous_jr.JobId, jcr->previous_jr.JobType, jcr->previous_jr.JobLevel); @@ -140,37 +146,37 @@ bool do_migration(JCR *jcr) LockRes(); job = (JOB *)GetResWithName(R_JOB, jcr->jr.Name); - tjob = (JOB *)GetResWithName(R_JOB, jcr->previous_jr.Name); + prev_job = (JOB *)GetResWithName(R_JOB, jcr->previous_jr.Name); UnlockRes(); - if (!job || !tjob) { + if (!job || !prev_job) { return false; } /* - * Target jcr is the new Job that corresponds to the original - * target job. It "runs" at the same time as the current + * prev_jcr is the new Job that corresponds to the original + * job. It "runs" at the same time as the current * migration job and becomes a new backup job that replaces * the original backup job. Most operations on the current - * migration jcr are also done on the target jcr. + * migration jcr are also done on the prev_jcr. */ - tjcr = jcr->previous_jcr = new_jcr(sizeof(JCR), dird_free_jcr); - memcpy(&tjcr->previous_jr, &jcr->previous_jr, sizeof(tjcr->previous_jr)); + prev_jcr = jcr->previous_jcr = new_jcr(sizeof(JCR), dird_free_jcr); + memcpy(&prev_jcr->previous_jr, &jcr->previous_jr, sizeof(prev_jcr->previous_jr)); - /* Turn the tjcr into a "real" job */ - set_jcr_defaults(tjcr, tjob); - if (!setup_job(tjcr)) { + /* Turn the prev_jcr into a "real" job */ + set_jcr_defaults(prev_jcr, prev_job); + if (!setup_job(prev_jcr)) { return false; } /* Set output PoolId and FileSetId. */ - tjcr->jr.PoolId = jcr->jr.PoolId; - tjcr->jr.FileSetId = jcr->jr.FileSetId; + prev_jcr->jr.PoolId = jcr->jr.PoolId; + prev_jcr->jr.FileSetId = jcr->jr.FileSetId; /* * Get the PoolId used with the original job. Then * find the pool name from the database record. */ memset(&pr, 0, sizeof(pr)); - pr.PoolId = tjcr->previous_jr.PoolId; + pr.PoolId = prev_jcr->previous_jr.PoolId; if (!db_get_pool_record(jcr, jcr->db, &pr)) { Jmsg(jcr, M_FATAL, 0, _("Pool for JobId %s not in database. ERR=%s\n"), edit_int64(pr.PoolId, ed1), db_strerror(jcr->db)); @@ -187,7 +193,7 @@ bool do_migration(JCR *jcr) /* ***FIXME*** */ /* If pool storage specified, use it for restore */ - copy_storage(tjcr, pool->storage); + copy_storage(prev_jcr, pool->storage); /* If the original backup pool has a NextPool, make sure a * record exists in the database. @@ -210,8 +216,8 @@ bool do_migration(JCR *jcr) * put the "NextPool" resource pointer in our jcr so that we * can pull the Storage reference from it. */ - tjcr->pool = jcr->pool = pool->NextPool; - tjcr->jr.PoolId = jcr->jr.PoolId = pr.PoolId; + prev_jcr->pool = jcr->pool = pool->NextPool; + prev_jcr->jr.PoolId = jcr->jr.PoolId = pr.PoolId; } /* If pool storage specified, use it instead of job storage for backup */ @@ -222,15 +228,15 @@ bool do_migration(JCR *jcr) edit_uint64(jcr->JobId, ed1), jcr->Job); set_jcr_job_status(jcr, JS_Running); - set_jcr_job_status(tjcr, JS_Running); + set_jcr_job_status(prev_jcr, JS_Running); Dmsg2(000, "JobId=%d JobLevel=%c\n", jcr->jr.JobId, jcr->jr.JobLevel); if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) { Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db)); return false; } - if (!db_update_job_start_record(tjcr, tjcr->db, &tjcr->jr)) { - Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(tjcr->db)); + if (!db_update_job_start_record(prev_jcr, prev_jcr->db, &prev_jcr->jr)) { + Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(prev_jcr->db)); return false; } @@ -243,7 +249,7 @@ bool do_migration(JCR *jcr) */ Dmsg0(110, "Open connection with storage daemon\n"); set_jcr_job_status(jcr, JS_WaitSD); - set_jcr_job_status(tjcr, JS_WaitSD); + set_jcr_job_status(prev_jcr, JS_WaitSD); /* * Start conversation with Storage daemon */ @@ -255,9 +261,9 @@ bool do_migration(JCR *jcr) * Now start a job with the Storage daemon */ Dmsg2(000, "Read store=%s, write store=%s\n", - ((STORE *)tjcr->storage->first())->hdr.name, + ((STORE *)prev_jcr->storage->first())->hdr.name, ((STORE *)jcr->storage->first())->hdr.name); - if (!start_storage_daemon_job(jcr, tjcr->storage, jcr->storage)) { + if (!start_storage_daemon_job(jcr, prev_jcr->storage, jcr->storage)) { return false; } Dmsg0(150, "Storage daemon connection OK\n"); @@ -279,13 +285,13 @@ bool do_migration(JCR *jcr) } set_jcr_job_status(jcr, JS_Running); - set_jcr_job_status(tjcr, JS_Running); + set_jcr_job_status(prev_jcr, JS_Running); /* Pickup Job termination data */ /* Note, the SD stores in jcr->JobFiles/ReadBytes/JobBytes/Errors */ wait_for_storage_daemon_termination(jcr); - jcr->JobStatus = jcr->SDJobStatus; + set_jcr_job_status(jcr, jcr->SDJobStatus); if (jcr->JobStatus == JS_Terminated) { migration_cleanup(jcr, jcr->JobStatus); return true; @@ -293,17 +299,26 @@ bool do_migration(JCR *jcr) return false; } +struct idpkt { + POOLMEM *list; + uint32_t count; +}; + /* - * Callback handler make list of JobIds + * Callback handler make list of DB Ids */ -static int jobid_handler(void *ctx, int num_fields, char **row) +static int dbid_handler(void *ctx, int num_fields, char **row) { - POOLMEM *JobIds = (POOLMEM *)ctx; + idpkt *ids = (idpkt *)ctx; - if (JobIds[0] != 0) { - pm_strcat(JobIds, ","); + Dmsg3(000, "count=%d Ids=%p %s\n", ids->count, ids->list, ids->list); + if (ids->count == 0) { + ids->list[0] = 0; + } else { + pm_strcat(ids->list, ","); } - pm_strcat(JobIds, row[0]); + pm_strcat(ids->list, row[0]); + ids->count++; return 0; } @@ -339,6 +354,47 @@ static int unique_name_handler(void *ctx, int num_fields, char **row) return 0; } +/* Get Job names in Pool */ +const char *sql_job = + "SELECT DISTINCT Job.Name from Job,Pool" + " WHERE Pool.Name='%s' AND Job.PoolId=Pool.PoolId"; + +/* Get JobIds from regex'ed Job names */ +const char *sql_jobids_from_job = + "SELECT DISTINCT Job.JobId FROM Job,Pool" + " WHERE Job.Name='%s' AND Pool.Name='%s' AND Job.PoolId=Pool.PoolId" + " ORDER by Job.StartTime"; + +/* Get Client names in Pool */ +const char *sql_client = + "SELECT DISTINCT Client.Name from Client,Pool,Job" + " WHERE Pool.Name='%s' AND Job.ClientId=Client.ClientId AND" + " Job.PoolId=Pool.PoolId"; + +/* Get JobIds from regex'ed Client names */ +const char *sql_jobids_from_client = + "SELECT DISTINCT Job.JobId FROM Job,Pool" + " WHERE Client.Name='%s' AND Pool.Name='%s' AND Job.PoolId=Pool.PoolId" + " AND Job.ClientId=Client.ClientId " + " ORDER by Job.StartTime"; + +/* Get Volume names in Pool */ +const char *sql_vol = + "SELECT DISTINCT VolumeName FROM Media,Pool WHERE" + " VolStatus in ('Full','Used','Error') AND" + " Media.PoolId=Pool.PoolId AND Pool.Name='%s'"; + +/* Get JobIds from regex'ed Volume names */ +const char *sql_jobids_from_vol = + "SELECT DISTINCT Job.JobId FROM Media,JobMedia,Job" + " WHERE Media.VolumeName='%s' AND Media.MediaId=JobMedia.MediaId" + " AND JobMedia.JobId=Job.JobId" + " ORDER by Job.StartTime"; + + + + + const char *sql_smallest_vol = "SELECT MediaId FROM Media,Pool WHERE" " VolStatus in ('Full','Used','Error') AND" @@ -367,31 +423,12 @@ const char *sql_vol_bytes = " Media.PoolId=Pool.PoolId AND Pool.Name='%s' AND" " VolBytes<%s ORDER BY LastWritten ASC LIMIT 1"; -const char *sql_client = - "SELECT DISTINCT Client.Name from Client,Pool,Media,Job,JobMedia " - " WHERE Media.PoolId=Pool.PoolId AND Pool.Name='%s' AND" - " JobMedia.JobId=Job.JobId AND Job.ClientId=Client.ClientId AND" - " Job.PoolId=Media.PoolId"; - -const char *sql_job = - "SELECT DISTINCT Job.Name from Job,Pool" - " WHERE Pool.Name='%s' AND Job.PoolId=Pool.PoolId"; - -const char *sql_jobids_from_job = - "SELECT DISTINCT Job.JobId FROM Job,Pool" - " WHERE Job.Name=%s AND Pool.Name='%s' AND Job.PoolId=Pool.PoolId" - " ORDER by Job.StartTime"; - const char *sql_ujobid = "SELECT DISTINCT Job.Job from Client,Pool,Media,Job,JobMedia " " WHERE Media.PoolId=Pool.PoolId AND Pool.Name='%s' AND" " JobMedia.JobId=Job.JobId AND Job.PoolId=Media.PoolId"; -const char *sql_vol = - "SELECT DISTINCT VolumeName FROM Media,Pool WHERE" - " VolStatus in ('Full','Used','Error') AND" - " Media.PoolId=Pool.PoolId AND Pool.Name='%s'"; /* @@ -402,253 +439,84 @@ static bool get_job_to_migrate(JCR *jcr) { char ed1[30]; POOL_MEM query(PM_MESSAGE); - POOLMEM *JobIds = get_pool_memory(PM_MESSAGE); JobId_t JobId; - int stat, rc; + int stat; char *p; - dlist *item_chain; - uitem *item = NULL; - uitem *last_item = NULL; - char prbuf[500]; - regex_t preg; + idpkt ids; + + ids.list = get_pool_memory(PM_MESSAGE); + Dmsg1(000, "list=%p\n", ids.list); + ids.list[0] = 0; + ids.count = 0; - JobIds[0] = 0; if (jcr->MigrateJobId != 0) { - jcr->previous_jr.JobId = jcr->MigrateJobId; Dmsg1(000, "previous jobid=%u\n", jcr->MigrateJobId); + edit_uint64(jcr->MigrateJobId, ids.list); + ids.count = 1; } else { switch (jcr->job->selection_type) { case MT_JOB: - if (!jcr->job->selection_pattern) { - Jmsg(jcr, M_FATAL, 0, _("No Migration Job selection pattern specified.\n")); + if (!regex_find_jobids(jcr, &ids, sql_job, sql_jobids_from_job, "Job")) { goto bail_out; - } - Dmsg1(000, "Job regex=%s\n", jcr->job->selection_pattern); - /* Complie regex expression */ - rc = regcomp(&preg, jcr->job->selection_pattern, REG_EXTENDED); - if (rc != 0) { - regerror(rc, &preg, prbuf, sizeof(prbuf)); - Jmsg(jcr, M_FATAL, 0, _("Could not compile regex pattern \"%s\" ERR=%s\n"), - jcr->job->selection_pattern, prbuf); + } + break; + case MT_CLIENT: + if (!regex_find_jobids(jcr, &ids, sql_client, + sql_jobids_from_client, "Client")) { goto bail_out; - } - item_chain = New(dlist(item, &item->link)); - /* Basic query for Job names */ - Mmsg(query, sql_job, jcr->pool->hdr.name); - Dmsg1(000, "query=%s\n", query.c_str()); - if (!db_sql_query(jcr->db, query.c_str(), unique_name_handler, - (void *)item_chain)) { - Jmsg(jcr, M_FATAL, 0, - _("SQL to get Job failed. ERR=%s\n"), db_strerror(jcr->db)); + } + break; + case MT_VOLUME: + if (!regex_find_jobids(jcr, &ids, sql_vol, + sql_jobids_from_vol, "Volume")) { goto bail_out; - } - /* Now apply the regex to the job names and remove any item not matched */ - foreach_dlist(item, item_chain) { - const int nmatch = 30; - regmatch_t pmatch[nmatch]; - if (last_item) { - free(last_item->item); - Dmsg1(000, "Remove item %s\n", last_item->item); - item_chain->remove(last_item); - } - Dmsg1(000, "Jobitem=%s\n", item->item); - rc = regexec(&preg, item->item, nmatch, pmatch, 0); - if (rc == 0) { - last_item = NULL; /* keep this one */ - } else { - last_item = item; - } - } - if (last_item) { - free(last_item->item); - Dmsg1(000, "Remove item %s\n", last_item->item); - item_chain->remove(last_item); - } - regfree(&preg); - /* - * At this point, we have a list of items in item_chain - * that have been matched by the regex, so now we need - * to look up their jobids. - */ - JobIds = get_pool_memory(PM_MESSAGE); - JobIds[0] = 0; - foreach_dlist(item, item_chain) { - Dmsg1(000, "Got Job: %s\n", item->item); - Mmsg(query, sql_jobids_from_job, item->item, jcr->pool->hdr.name); - if (!db_sql_query(jcr->db, query.c_str(), jobid_handler, (void *)JobIds)) { - Jmsg(jcr, M_FATAL, 0, - _("SQL failed. ERR=%s\n"), db_strerror(jcr->db)); - goto bail_out; - } - } - if (JobIds[0] == 0) { - Jmsg(jcr, M_INFO, 0, _("No jobs found to migrate.\n")); - goto ok_out; - } - Dmsg1(000, "Job Jobids=%s\n", JobIds); - free_pool_memory(JobIds); - delete item_chain; + } break; - case MT_SMALLEST_VOL: - Mmsg(query, sql_smallest_vol, jcr->pool->hdr.name); - JobIds = get_pool_memory(PM_MESSAGE); - JobIds[0] = 0; - if (!db_sql_query(jcr->db, query.c_str(), jobid_handler, (void *)JobIds)) { - Jmsg(jcr, M_FATAL, 0, - _("SQL to get Volume failed. ERR=%s\n"), db_strerror(jcr->db)); + case MT_SQLQUERY: + if (!jcr->job->selection_pattern) { + Jmsg(jcr, M_FATAL, 0, _("No Migration SQL selection pattern specified.\n")); goto bail_out; } - if (JobIds[0] == 0) { - Jmsg(jcr, M_INFO, 0, _("No Volumes found to migrate.\n")); - goto ok_out; - } - /* ***FIXME*** must loop over JobIds */ - Mmsg(query, sql_jobids_from_mediaid, JobIds); - JobIds[0] = 0; - if (!db_sql_query(jcr->db, query.c_str(), jobid_handler, (void *)JobIds)) { + Dmsg1(000, "SQL=%s\n", jcr->job->selection_pattern); + if (!db_sql_query(jcr->db, jcr->job->selection_pattern, + dbid_handler, (void *)&ids)) { Jmsg(jcr, M_FATAL, 0, - _("SQL to get Volume failed. ERR=%s\n"), db_strerror(jcr->db)); + _("SQL failed. ERR=%s\n"), db_strerror(jcr->db)); goto bail_out; } - Dmsg1(000, "Smallest Vol Jobids=%s\n", JobIds); + break; + + +/***** Below not implemented yet *********/ + case MT_SMALLEST_VOL: + Mmsg(query, sql_smallest_vol, jcr->pool->hdr.name); +// Mmsg(query2, sql_jobids_from_mediaid, JobIds); +// Dmsg1(000, "Smallest Vol Jobids=%s\n", JobIds); break; case MT_OLDEST_VOL: Mmsg(query, sql_oldest_vol, jcr->pool->hdr.name); - JobIds = get_pool_memory(PM_MESSAGE); - JobIds[0] = 0; - if (!db_sql_query(jcr->db, query.c_str(), jobid_handler, (void *)JobIds)) { - Jmsg(jcr, M_FATAL, 0, - _("SQL to get Volume failed. ERR=%s\n"), db_strerror(jcr->db)); - goto bail_out; - } - if (JobIds[0] == 0) { - Jmsg(jcr, M_INFO, 0, _("No Volume found to migrate.\n")); - goto ok_out; - } - Mmsg(query, sql_jobids_from_mediaid, JobIds); - JobIds[0] = 0; - if (!db_sql_query(jcr->db, query.c_str(), jobid_handler, (void *)JobIds)) { - Jmsg(jcr, M_FATAL, 0, - _("SQL to get Volume failed. ERR=%s\n"), db_strerror(jcr->db)); - goto bail_out; - } - Dmsg1(000, "Oldest Vol Jobids=%s\n", JobIds); +// Mmsg(query2, sql_jobids_from_mediaid, JobIds); +// Dmsg1(000, "Oldest Vol Jobids=%s\n", JobIds); break; case MT_POOL_OCCUPANCY: Mmsg(query, sql_pool_bytes, jcr->pool->hdr.name); - JobIds = get_pool_memory(PM_MESSAGE); - JobIds[0] = 0; - if (!db_sql_query(jcr->db, query.c_str(), jobid_handler, (void *)JobIds)) { - Jmsg(jcr, M_FATAL, 0, - _("SQL to get Volume failed. ERR=%s\n"), db_strerror(jcr->db)); - goto bail_out; - } - if (JobIds[0] == 0) { - Jmsg(jcr, M_INFO, 0, _("No jobs found to migrate.\n")); - goto ok_out; - } - Dmsg1(000, "Pool Occupancy Jobids=%s\n", JobIds); +// Dmsg1(000, "Pool Occupancy Jobids=%s\n", JobIds); break; case MT_POOL_TIME: Dmsg0(000, "Pool time not implemented\n"); break; - case MT_CLIENT: - if (!jcr->job->selection_pattern) { - Jmsg(jcr, M_FATAL, 0, _("No Migration Client selection pattern specified.\n")); - goto bail_out; - } - Dmsg1(000, "Client regex=%s\n", jcr->job->selection_pattern); - rc = regcomp(&preg, jcr->job->selection_pattern, REG_EXTENDED); - if (rc != 0) { - regerror(rc, &preg, prbuf, sizeof(prbuf)); - Jmsg(jcr, M_FATAL, 0, _("Could not compile regex pattern \"%s\" ERR=%s\n"), - jcr->job->selection_pattern, prbuf); - } - item_chain = New(dlist(item, &item->link)); - Mmsg(query, sql_client, jcr->pool->hdr.name); - Dmsg1(100, "query=%s\n", query.c_str()); - if (!db_sql_query(jcr->db, query.c_str(), unique_name_handler, - (void *)item_chain)) { - Jmsg(jcr, M_FATAL, 0, - _("SQL to get Client failed. ERR=%s\n"), db_strerror(jcr->db)); - goto bail_out; - } - /* Now apply the regex and create the jobs */ - foreach_dlist(item, item_chain) { - const int nmatch = 30; - regmatch_t pmatch[nmatch]; - rc = regexec(&preg, item->item, nmatch, pmatch, 0); - if (rc == 0) { - Dmsg1(000, "Do Client=%s\n", item->item); - } - free(item->item); - } - regfree(&preg); - delete item_chain; - break; - case MT_VOLUME: - if (!jcr->job->selection_pattern) { - Jmsg(jcr, M_FATAL, 0, _("No Migration Volume selection pattern specified.\n")); - goto bail_out; - } - Dmsg1(000, "Volume regex=%s\n", jcr->job->selection_pattern); - rc = regcomp(&preg, jcr->job->selection_pattern, REG_EXTENDED); - if (rc != 0) { - regerror(rc, &preg, prbuf, sizeof(prbuf)); - Jmsg(jcr, M_FATAL, 0, _("Could not compile regex pattern \"%s\" ERR=%s\n"), - jcr->job->selection_pattern, prbuf); - } - item_chain = New(dlist(item, &item->link)); - Mmsg(query, sql_vol, jcr->pool->hdr.name); - Dmsg1(100, "query=%s\n", query.c_str()); - if (!db_sql_query(jcr->db, query.c_str(), unique_name_handler, - (void *)item_chain)) { - Jmsg(jcr, M_FATAL, 0, - _("SQL to get Job failed. ERR=%s\n"), db_strerror(jcr->db)); - goto bail_out; - } - /* Now apply the regex and create the jobs */ - foreach_dlist(item, item_chain) { - const int nmatch = 30; - regmatch_t pmatch[nmatch]; - rc = regexec(&preg, item->item, nmatch, pmatch, 0); - if (rc == 0) { - Dmsg1(000, "Do Vol=%s\n", item->item); - } - free(item->item); - } - regfree(&preg); - delete item_chain; - break; - case MT_SQLQUERY: - JobIds[0] = 0; - if (!jcr->job->selection_pattern) { - Jmsg(jcr, M_FATAL, 0, _("No Migration SQL selection pattern specified.\n")); - goto bail_out; - } - Dmsg1(000, "SQL=%s\n", jcr->job->selection_pattern); - if (!db_sql_query(jcr->db, query.c_str(), jobid_handler, (void *)JobIds)) { - Jmsg(jcr, M_FATAL, 0, - _("SQL to get Volume failed. ERR=%s\n"), db_strerror(jcr->db)); - goto bail_out; - } - if (JobIds[0] == 0) { - Jmsg(jcr, M_INFO, 0, _("No jobs found to migrate.\n")); - goto ok_out; - } - Dmsg1(000, "Jobids=%s\n", JobIds); - goto bail_out; - break; default: Jmsg(jcr, M_FATAL, 0, _("Unknown Migration Selection Type.\n")); goto bail_out; } } - p = JobIds; + p = ids.list; JobId = 0; stat = get_next_jobid_from_list(&p, &JobId); Dmsg2(000, "get_next_jobid stat=%d JobId=%u\n", stat, JobId); + jcr->MigrateJobId = JobId; + start_migration_job(jcr); if (stat < 0) { Jmsg(jcr, M_FATAL, 0, _("Invalid JobId found.\n")); goto bail_out; @@ -658,7 +526,7 @@ static bool get_job_to_migrate(JCR *jcr) } jcr->previous_jr.JobId = JobId; - Dmsg1(000, "Last jobid=%d\n", jcr->previous_jr.JobId); + Dmsg1(000, "Previous jobid=%d\n", jcr->previous_jr.JobId); if (!db_get_job_record(jcr, jcr->db, &jcr->previous_jr)) { Jmsg(jcr, M_FATAL, 0, _("Could not get job record for JobId %s to migrate. ERR=%s"), @@ -670,14 +538,119 @@ static bool get_job_to_migrate(JCR *jcr) jcr->previous_jr.JobId, jcr->previous_jr.Job); ok_out: - free_pool_memory(JobIds); + free_pool_memory(ids.list); return true; bail_out: - free_pool_memory(JobIds); + free_pool_memory(ids.list); return false; } +static void start_migration_job(JCR *jcr) +{ + UAContext *ua = new_ua_context(jcr); + char ed1[50]; + ua->batch = true; + Mmsg(ua->cmd, "run %s jobid=%s", jcr->job->hdr.name, + edit_uint64(jcr->MigrateJobId, ed1)); + Dmsg1(000, "=============== Migration cmd=%s\n", ua->cmd); + parse_ua_args(ua); /* parse command */ +// int stat = run_cmd(ua, ua->cmd); + int stat = (int)jcr->MigrateJobId; + if (stat == 0) { + Jmsg(jcr, M_ERROR, 0, _("Could not start migration job.\n")); + } else { + Jmsg(jcr, M_INFO, 0, _("Migration JobId %d started.\n"), stat); + } + free_ua_context(ua); +} + + +static bool regex_find_jobids(JCR *jcr, idpkt *ids, const char *query1, + const char *query2, const char *type) { + dlist *item_chain; + uitem *item = NULL; + uitem *last_item = NULL; + regex_t preg; + char prbuf[500]; + int rc; + bool ok = false; + POOL_MEM query(PM_MESSAGE); + + item_chain = New(dlist(item, &item->link)); + if (!jcr->job->selection_pattern) { + Jmsg(jcr, M_FATAL, 0, _("No Migration %s selection pattern specified.\n"), + type); + goto bail_out; + } + Dmsg1(000, "regex=%s\n", jcr->job->selection_pattern); + /* Compile regex expression */ + rc = regcomp(&preg, jcr->job->selection_pattern, REG_EXTENDED); + if (rc != 0) { + regerror(rc, &preg, prbuf, sizeof(prbuf)); + Jmsg(jcr, M_FATAL, 0, _("Could not compile regex pattern \"%s\" ERR=%s\n"), + jcr->job->selection_pattern, prbuf); + goto bail_out; + } + /* Basic query for names */ + Mmsg(query, query1, jcr->pool->hdr.name); + Dmsg1(000, "query1=%s\n", query.c_str()); + if (!db_sql_query(jcr->db, query.c_str(), unique_name_handler, + (void *)item_chain)) { + Jmsg(jcr, M_FATAL, 0, + _("SQL to get %s failed. ERR=%s\n"), type, db_strerror(jcr->db)); + goto bail_out; + } + /* Now apply the regex to the names and remove any item not matched */ + foreach_dlist(item, item_chain) { + const int nmatch = 30; + regmatch_t pmatch[nmatch]; + if (last_item) { + Dmsg1(000, "Remove item %s\n", last_item->item); + free(last_item->item); + item_chain->remove(last_item); + } + Dmsg1(000, "Jobitem=%s\n", item->item); + rc = regexec(&preg, item->item, nmatch, pmatch, 0); + if (rc == 0) { + last_item = NULL; /* keep this one */ + } else { + last_item = item; + } + } + if (last_item) { + free(last_item->item); + Dmsg1(000, "Remove item %s\n", last_item->item); + item_chain->remove(last_item); + } + regfree(&preg); + /* + * At this point, we have a list of items in item_chain + * that have been matched by the regex, so now we need + * to look up their jobids. + */ + ids->count = 0; + foreach_dlist(item, item_chain) { + Dmsg1(000, "Got Job: %s\n", item->item); + Mmsg(query, query2, item->item, jcr->pool->hdr.name); + Dmsg1(000, "query2=%s\n", query.c_str()); + if (!db_sql_query(jcr->db, query.c_str(), dbid_handler, (void *)ids)) { + Jmsg(jcr, M_FATAL, 0, + _("SQL failed. ERR=%s\n"), db_strerror(jcr->db)); + goto bail_out; + } + } + if (ids->count == 0) { + Jmsg(jcr, M_INFO, 0, _("No %ss found to migrate.\n"), type); + } + ok = true; +bail_out: + Dmsg2(000, "Count=%d Jobids=%s\n", ids->count, ids->list); + delete item_chain; + Dmsg0(000, "After delete item_chain\n"); + return ok; +} + /* * Release resources allocated during backup. @@ -686,6 +659,7 @@ void migration_cleanup(JCR *jcr, int TermCode) { char sdt[MAX_TIME_LENGTH], edt[MAX_TIME_LENGTH]; char ec1[30], ec2[30], ec3[30], ec4[30], ec5[30], elapsed[50]; + char ec6[50], ec7[50], ec8[50]; char term_code[100], sd_term_msg[100]; const char *term_msg; int msg_type; @@ -710,7 +684,6 @@ void migration_cleanup(JCR *jcr, int TermCode) set_jcr_job_status(prev_jcr, TermCode); - update_job_end_record(prev_jcr); Mmsg(query, "UPDATE Job SET StartTime='%s',EndTime='%s'," @@ -789,19 +762,17 @@ void migration_cleanup(JCR *jcr, int TermCode) if (RunTime <= 0) { kbps = 0; } else { - kbps = (double)jcr->jr.JobBytes / (1000 * RunTime); + kbps = (double)jcr->SDJobBytes / (1000 * RunTime); } jobstatus_to_ascii(jcr->SDJobStatus, sd_term_msg, sizeof(sd_term_msg)); -// bmicrosleep(15, 0); /* for debugging SIGHUP */ - Jmsg(jcr, msg_type, 0, _("Bacula %s (%s): %s\n" -" Old Backup JobId: %u\n" -" New Backup JobId: %u\n" -" JobId: %u\n" -" Job: %s\n" +" Prev Backup JobId: %s\n" +" New Backup JobId: %s\n" +" Migration JobId: %s\n" +" Migration Job: %s\n" " Backup Level: %s%s\n" " Client: %s\n" " FileSet: \"%s\" %s\n" @@ -823,9 +794,9 @@ void migration_cleanup(JCR *jcr, int TermCode) VERSION, LSMDATE, edt, - prev_jcr ? jcr->previous_jr.JobId : 0, - prev_jcr ? prev_jcr->jr.JobId : 0, - jcr->jr.JobId, + prev_jcr ? edit_uint64(jcr->previous_jr.JobId, ec6) : "0", + prev_jcr ? edit_uint64(prev_jcr->jr.JobId, ec7) : "0", + edit_uint64(jcr->jr.JobId, ec8), jcr->jr.Job, level_to_str(jcr->JobLevel), jcr->since, jcr->client->hdr.name, @@ -837,7 +808,7 @@ void migration_cleanup(JCR *jcr, int TermCode) jcr->JobPriority, edit_uint64_with_commas(jcr->SDJobFiles, ec1), edit_uint64_with_commas(jcr->SDJobBytes, ec2), - edit_uint64_with_suffix(jcr->jr.JobBytes, ec3), + edit_uint64_with_suffix(jcr->SDJobBytes, ec3), (float)kbps, prev_jcr ? prev_jcr->VolumeName : "", jcr->VolSessionId, @@ -848,8 +819,10 @@ void migration_cleanup(JCR *jcr, int TermCode) sd_term_msg, term_code); - Dmsg1(100, "Leave migrate_cleanup() previous_jcr=0x%x\n", jcr->previous_jcr); + Dmsg1(100, "migrate_cleanup() previous_jcr=0x%x\n", jcr->previous_jcr); if (jcr->previous_jcr) { free_jcr(jcr->previous_jcr); + jcr->previous_jcr = NULL; } + Dmsg0(100, "Leave migrate_cleanup()\n"); }