/* * Prune Job stat records from the database. */ static bool prune_stats(UAContext *ua, utime_t retention) { char ed1[50]; char dt[MAX_TIME_LENGTH]; POOL_MEM query(PM_MESSAGE); utime_t now = (utime_t)time(NULL); db_lock(ua->db); Mmsg(query, "DELETE FROM JobHisto WHERE JobTDate < %s", edit_int64(now - retention, ed1)); db_sql_query(ua->db, query.c_str()); db_unlock(ua->db); ua->info_msg(_("Pruned Jobs from JobHisto in catalog.\n")); bstrutime(dt, sizeof(dt), now - retention); db_lock(ua->db); Mmsg(query, "DELETE FROM DeviceStats WHERE SampleTime < '%s'", dt); db_sql_query(ua->db, query.c_str()); db_unlock(ua->db); ua->info_msg(_("Pruned Statistics from DeviceStats in catalog.\n")); db_lock(ua->db); Mmsg(query, "DELETE FROM JobStats WHERE SampleTime < '%s'", dt); db_sql_query(ua->db, query.c_str()); db_unlock(ua->db); ua->info_msg(_("Pruned Statistics from JobStats in catalog.\n")); return true; }
/* * This routine will purge (delete) all records * associated with a particular Volume. It will * not delete the media record itself. * TODO: This function is broken and it doesn't purge * File, BaseFiles, Log, ... * We call it from relabel and delete volume=, both ensure * that the volume is properly purged. */ static int do_media_purge(B_DB *mdb, MEDIA_DBR *mr) { POOLMEM *query = get_pool_memory(PM_MESSAGE); struct s_del_ctx del; char ed1[50]; int i; del.num_ids = 0; del.tot_ids = 0; del.num_del = 0; del.max_ids = 0; Mmsg(mdb->cmd, "SELECT JobId from JobMedia WHERE MediaId=%d", mr->MediaId); del.max_ids = mr->VolJobs; if (del.max_ids < 100) { del.max_ids = 100; } else if (del.max_ids > MAX_DEL_LIST_LEN) { del.max_ids = MAX_DEL_LIST_LEN; } del.JobId = (JobId_t *)malloc(sizeof(JobId_t) * del.max_ids); db_sql_query(mdb, mdb->cmd, delete_handler, (void *)&del); for (i=0; i < del.num_ids; i++) { Dmsg1(400, "Delete JobId=%d\n", del.JobId[i]); Mmsg(query, "DELETE FROM Job WHERE JobId=%s", edit_int64(del.JobId[i], ed1)); db_sql_query(mdb, query); Mmsg(query, "DELETE FROM File WHERE JobId=%s", edit_int64(del.JobId[i], ed1)); db_sql_query(mdb, query); Mmsg(query, "DELETE FROM JobMedia WHERE JobId=%s", edit_int64(del.JobId[i], ed1)); db_sql_query(mdb, query); } free(del.JobId); free_pool_memory(query); return 1; }
/* * Remove all records from catalog for a list of JobIds */ void purge_jobs_from_catalog(UAContext *ua, char *jobs) { POOL_MEM query(PM_MESSAGE); /* Delete (or purge) records associated with the job */ purge_files_from_jobs(ua, jobs); Mmsg(query, "DELETE FROM JobMedia WHERE JobId IN (%s)", jobs); db_sql_query(ua->db, query.c_str()); Dmsg1(050, "Delete JobMedia sql=%s\n", query.c_str()); Mmsg(query, "DELETE FROM Log WHERE JobId IN (%s)", jobs); db_sql_query(ua->db, query.c_str()); Dmsg1(050, "Delete Log sql=%s\n", query.c_str()); Mmsg(query, "DELETE FROM RestoreObject WHERE JobId IN (%s)", jobs); db_sql_query(ua->db, query.c_str()); Dmsg1(050, "Delete RestoreObject sql=%s\n", query.c_str()); Mmsg(query, "DELETE FROM PathVisibility WHERE JobId IN (%s)", jobs); db_sql_query(ua->db, query.c_str()); Dmsg1(050, "Delete PathVisibility sql=%s\n", query.c_str()); upgrade_copies(ua, jobs); /* Now remove the Job record itself */ Mmsg(query, "DELETE FROM Job WHERE JobId IN (%s)", jobs); db_sql_query(ua->db, query.c_str()); Dmsg1(050, "Delete Job sql=%s\n", query.c_str()); }
static bool create_temp_tables(UAContext *ua) { /* Create temp tables and indicies */ if (!db_sql_query(ua->db, create_deltabs[db_get_type_index(ua->db)])) { ua->error_msg("%s", db_strerror(ua->db)); Dmsg0(050, "create DelTables table failed\n"); return false; } if (!db_sql_query(ua->db, create_delindex)) { ua->error_msg("%s", db_strerror(ua->db)); Dmsg0(050, "create DelInx1 index failed\n"); return false; } return true; }
/* * For a given file (path+filename), split into path and file, then * lookup the most recent backup in the catalog to get the JobId * and FileIndex, then insert them into the findex list. */ static bool insert_file_into_findex_list(UAContext *ua, RESTORE_CTX *rx, char *file, char *date) { strip_trailing_newline(file); split_path_and_filename(ua, rx, file); if (*rx->JobIds == 0) { Mmsg(rx->query, uar_jobid_fileindex, date, rx->path, rx->fname, rx->ClientName); } else { Mmsg(rx->query, uar_jobids_fileindex, rx->JobIds, date, rx->path, rx->fname, rx->ClientName); } rx->found = false; /* Find and insert jobid and File Index */ if (!db_sql_query(ua->db, rx->query, jobid_fileindex_handler, (void *)rx)) { ua->error_msg(_("Query failed: %s. ERR=%s\n"), rx->query, db_strerror(ua->db)); } if (!rx->found) { ua->error_msg(_("No database record found for: %s\n"), file); // ua->error_msg("Query=%s\n", rx->query); return true; } return true; }
static void drop_temp_tables(UAContext *ua) { int i; for (i=0; drop_deltabs[i]; i++) { db_sql_query(ua->db, drop_deltabs[i]); } }
/* * Get prune list for a volume */ int get_prune_list_for_volume(UAContext *ua, MEDIA_DBR *mr, del_ctx *del) { POOL_MEM query(PM_MESSAGE); int count = 0; utime_t now, period; char ed1[50], ed2[50]; if (mr->Enabled == 2) { return 0; /* cannot prune Archived volumes */ } /* * Now add to the list of JobIds for Jobs written to this Volume */ edit_int64(mr->MediaId, ed1); period = mr->VolRetention; now = (utime_t)time(NULL); edit_int64(now-period, ed2); Mmsg(query, sel_JobMedia, ed1, ed2); Dmsg3(250, "Now=%d period=%d now-period=%s\n", (int)now, (int)period, ed2); Dmsg1(050, "Query=%s\n", query.c_str()); if (!db_sql_query(ua->db, query.c_str(), file_delete_handler, (void *)del)) { if (ua->verbose) { ua->error_msg("%s", db_strerror(ua->db)); } Dmsg0(050, "Count failed\n"); goto bail_out; } count = exclude_running_jobs_from_list(del); bail_out: return count; }
/* * Check catalog max_connections setting */ bool db_check_max_connections(JCR *jcr, B_DB *mdb, uint32_t max_concurrent_jobs) { struct max_connections_context context; /* Without Batch insert, no need to verify max_connections */ if (!mdb->batch_insert_available()) return true; context.db = mdb; context.nr_connections = 0; /* Check max_connections setting */ if (!db_sql_query(mdb, sql_get_max_connections[db_get_type_index(mdb)], db_max_connections_handler, &context)) { Jmsg(jcr, M_ERROR, 0, "Can't verify max_connections settings %s", mdb->errmsg); return false; } if (context.nr_connections && max_concurrent_jobs && max_concurrent_jobs > context.nr_connections) { Mmsg(mdb->errmsg, _("Potential performance problem:\n" "max_connections=%d set for %s database \"%s\" should be larger than Director's " "MaxConcurrentJobs=%d\n"), context.nr_connections, db_get_type(mdb), mdb->get_db_name(), max_concurrent_jobs); Jmsg(jcr, M_WARNING, 0, "%s", mdb->errmsg); return false; } return true; }
/* Modify the RecyclePool of a Volume */ void update_vol_recyclepool(UAContext *ua, char *val, MEDIA_DBR *mr) { POOL_DBR pr; POOL_MEM query(PM_MESSAGE); char ed1[50], ed2[50], *poolname; if(val && *val) { /* update volume recyclepool="Scratch" */ /* If a pool name is given, look up the PoolId */ memset(&pr, 0, sizeof(pr)); bstrncpy(pr.Name, val, sizeof(pr.Name)); if (!get_pool_dbr(ua, &pr, NT_("recyclepool"))) { return; } /* pool = select_pool_resource(ua); */ mr->RecyclePoolId = pr.PoolId; /* get the PoolId */ poolname = pr.Name; } else { /* update volume recyclepool="" */ /* If no pool name is given, set the PoolId to 0 (the default) */ mr->RecyclePoolId = 0; poolname = _("*None*"); } db_lock(ua->db); Mmsg(query, "UPDATE Media SET RecyclePoolId=%s WHERE MediaId=%s", edit_int64(mr->RecyclePoolId, ed1), edit_int64(mr->MediaId, ed2)); if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) { ua->error_msg("%s", db_strerror(ua->db)); } else { ua->info_msg(_("New RecyclePool is: %s\n"), poolname); } db_unlock(ua->db); }
/* * This routine returns: * false if an error occurred * true otherwise * ids.count number of jobids found (may be zero) */ static bool find_jobids_of_pool_uncopied_jobs(JCR *jcr, idpkt *ids) { bool ok = false; POOL_MEM query(PM_MESSAGE); /* Only a copy job is allowed */ if (jcr->getJobType() != JT_COPY) { Jmsg(jcr, M_FATAL, 0, _("Selection Type 'pooluncopiedjobs' only applies to Copy Jobs")); goto bail_out; } Dmsg1(dbglevel, "copy selection pattern=%s\n", jcr->rpool->name()); Mmsg(query, sql_jobids_of_pool_uncopied_jobs, jcr->rpool->name()); Dmsg1(dbglevel, "get uncopied jobs query=%s\n", query.c_str()); if (!db_sql_query(jcr->db, query.c_str(), unique_dbid_handler, (void *)ids)) { Jmsg(jcr, M_FATAL, 0, _("SQL to get uncopied jobs failed. ERR=%s\n"), db_strerror(jcr->db)); goto bail_out; } ok = true; bail_out: return ok; }
static bool build_directory_tree(UAContext *ua, RESTORE_CTX *rx) { TREE_CTX tree; JobId_t JobId, last_JobId; char *p; bool OK = true; char ed1[50]; memset(&tree, 0, sizeof(TREE_CTX)); /* * Build the directory tree containing JobIds user selected */ tree.root = new_tree(rx->TotalFiles); tree.ua = ua; tree.all = rx->all; last_JobId = 0; /* * For display purposes, the same JobId, with different volumes may * appear more than once, however, we only insert it once. */ p = rx->JobIds; tree.FileEstimate = 0; if (get_next_jobid_from_list(&p, &JobId) > 0) { /* Use first JobId as estimate of the number of files to restore */ Mmsg(rx->query, uar_count_files, edit_int64(JobId, ed1)); if (!db_sql_query(ua->db, rx->query, restore_count_handler, (void *)rx)) { ua->error_msg("%s\n", db_strerror(ua->db)); } if (rx->found) { /* Add about 25% more than this job for over estimate */ tree.FileEstimate = rx->JobId + (rx->JobId >> 2); tree.DeltaCount = rx->JobId/50; /* print 50 ticks */ }
/* Modify the Pool in which this Volume is located */ void update_vol_pool(UAContext *ua, char *val, MEDIA_DBR *mr, POOL_DBR *opr) { POOL_DBR pr; POOL_MEM query(PM_MESSAGE); char ed1[50], ed2[50]; memset(&pr, 0, sizeof(pr)); bstrncpy(pr.Name, val, sizeof(pr.Name)); if (!get_pool_dbr(ua, &pr)) { return; } mr->PoolId = pr.PoolId; /* set new PoolId */ /* */ db_lock(ua->db); Mmsg(query, "UPDATE Media SET PoolId=%s WHERE MediaId=%s", edit_int64(mr->PoolId, ed1), edit_int64(mr->MediaId, ed2)); if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) { ua->error_msg("%s", db_strerror(ua->db)); } else { ua->info_msg(_("New Pool is: %s\n"), pr.Name); opr->NumVols--; if (!db_update_pool_record(ua->jcr, ua->db, opr)) { ua->error_msg("%s", db_strerror(ua->db)); } pr.NumVols++; if (!db_update_pool_record(ua->jcr, ua->db, &pr)) { ua->error_msg("%s", db_strerror(ua->db)); } } db_unlock(ua->db); }
static void update_volmaxfiles(UAContext *ua, char *val, MEDIA_DBR *mr) { POOL_MEM query(PM_MESSAGE); char ed1[50]; Mmsg(query, "UPDATE Media SET MaxVolFiles=%s WHERE MediaId=%s", val, edit_int64(mr->MediaId, ed1)); if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) { ua->error_msg("%s", db_strerror(ua->db)); } else { ua->info_msg(_("New max files is: %s\n"), val); } }
/* * Change the type of the next copy job to backup. * We need to upgrade the next copy of a normal job, * and also upgrade the next copy when the normal job * already have been purged. * * JobId: 1 PriorJobId: 0 (original) * JobId: 2 PriorJobId: 1 (first copy) * JobId: 3 PriorJobId: 1 (second copy) * * JobId: 2 PriorJobId: 1 (first copy, now regular backup) * JobId: 3 PriorJobId: 1 (second copy) * * => Search through PriorJobId in jobid and * PriorJobId in PriorJobId (jobid) */ void upgrade_copies(UAContext *ua, char *jobs) { POOL_MEM query(PM_MESSAGE); db_lock(ua->db); /* Do it in two times for mysql */ Mmsg(query, uap_upgrade_copies_oldest_job[db_get_type_index(ua->db)], JT_JOB_COPY, jobs, jobs); db_sql_query(ua->db, query.c_str()); Dmsg1(050, "Upgrade copies Log sql=%s\n", query.c_str()); /* Now upgrade first copy to Backup */ Mmsg(query, "UPDATE Job SET Type='B' " /* JT_JOB_COPY => JT_BACKUP */ "WHERE JobId IN ( SELECT JobId FROM cpy_tmp )"); db_sql_query(ua->db, query.c_str()); Mmsg(query, "DROP TABLE cpy_tmp"); db_sql_query(ua->db, query.c_str()); db_unlock(ua->db); }
/* * Remove File records from a list of JobIds */ void purge_files_from_jobs(UAContext *ua, char *jobs) { POOL_MEM query(PM_MESSAGE); Mmsg(query, "DELETE FROM File WHERE JobId IN (%s)", jobs); db_sql_query(ua->db, query.c_str()); Dmsg1(050, "Delete File sql=%s\n", query.c_str()); Mmsg(query, "DELETE FROM BaseFiles WHERE JobId IN (%s)", jobs); db_sql_query(ua->db, query.c_str()); Dmsg1(050, "Delete BaseFiles sql=%s\n", query.c_str()); /* * Now mark Job as having files purged. This is necessary to * avoid having too many Jobs to process in future prunings. If * we don't do this, the number of JobId's in our in memory list * could grow very large. */ Mmsg(query, "UPDATE Job SET PurgedFiles=1 WHERE JobId IN (%s)", jobs); db_sql_query(ua->db, query.c_str()); Dmsg1(050, "Mark purged sql=%s\n", query.c_str()); }
/* Prune Job stat records from the database. * */ int prune_stats(UAContext *ua, utime_t retention) { char ed1[50]; POOL_MEM query(PM_MESSAGE); utime_t now = (utime_t)time(NULL); db_lock(ua->db); Mmsg(query, "DELETE FROM JobHisto WHERE JobTDate < %s", edit_int64(now - retention, ed1)); db_sql_query(ua->db, query.c_str()); db_unlock(ua->db); ua->info_msg(_("Pruned Jobs from JobHisto catalog.\n")); return true; }
static void update_volretention(UAContext *ua, char *val, MEDIA_DBR *mr) { char ed1[150], ed2[50]; POOL_MEM query(PM_MESSAGE); if (!duration_to_utime(val, &mr->VolRetention)) { ua->error_msg(_("Invalid retention period specified: %s\n"), val); return; } Mmsg(query, "UPDATE Media SET VolRetention=%s WHERE MediaId=%s", edit_uint64(mr->VolRetention, ed1), edit_int64(mr->MediaId,ed2)); if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) { ua->error_msg("%s", db_strerror(ua->db)); } else { ua->info_msg(_("New retention period is: %s\n"), edit_utime(mr->VolRetention, ed1, sizeof(ed1))); } }
/* Check that the tables correspond to the version we want */ bool check_tables_version(JCR *jcr, B_DB *mdb) { uint32_t bareos_db_version = 0; const char *query = "SELECT VersionId FROM Version"; if (!db_sql_query(mdb, query, db_int_handler, (void *)&bareos_db_version)) { Jmsg(jcr, M_FATAL, 0, "%s", mdb->errmsg); return false; } if (bareos_db_version != BDB_VERSION) { Mmsg(mdb->errmsg, "Version error for database \"%s\". Wanted %d, got %d\n", mdb->get_db_name(), BDB_VERSION, bareos_db_version); Jmsg(jcr, M_FATAL, 0, "%s", mdb->errmsg); return false; } return true; }
/* * Get the JobId and FileIndexes of all files in the specified table */ static bool insert_table_into_findex_list(UAContext *ua, RESTORE_CTX *rx, char *table) { strip_trailing_junk(table); Mmsg(rx->query, uar_jobid_fileindex_from_table, table); rx->found = false; /* Find and insert jobid and File Index */ if (!db_sql_query(ua->db, rx->query, jobid_fileindex_handler, (void *)rx)) { ua->error_msg(_("Query failed: %s. ERR=%s\n"), rx->query, db_strerror(ua->db)); } if (!rx->found) { ua->error_msg(_("No table found: %s\n"), table); return true; } return true; }
static void update_volmaxbytes(UAContext *ua, char *val, MEDIA_DBR *mr) { uint64_t maxbytes; char ed1[50], ed2[50]; POOL_MEM query(PM_MESSAGE); if (!size_to_uint64(val, strlen(val), &maxbytes)) { ua->error_msg(_("Invalid max. bytes specification: %s\n"), val); return; } Mmsg(query, "UPDATE Media SET MaxVolBytes=%s WHERE MediaId=%s", edit_uint64(maxbytes, ed1), edit_int64(mr->MediaId, ed2)); if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) { ua->error_msg("%s", db_strerror(ua->db)); } else { ua->info_msg(_("New Max bytes is: %s\n"), edit_uint64(maxbytes, ed1)); } }
static void update_volrecycle(UAContext *ua, char *val, MEDIA_DBR *mr) { int recycle; char ed1[50]; POOL_MEM query(PM_MESSAGE); if (!is_yesno(val, &recycle)) { ua->error_msg(_("Invalid value. It must be yes or no.\n")); return; } Mmsg(query, "UPDATE Media SET Recycle=%d WHERE MediaId=%s", recycle, edit_int64(mr->MediaId, ed1)); if (!db_sql_query(ua->db, query.c_str())) { ua->error_msg("%s", db_strerror(ua->db)); } else { ua->info_msg(_("New Recycle flag is: %s\n"), recycle==1?_("yes"):_("no")); } }
/* * This routine returns: * false if an error occurred * true otherwise * ids.count number of jobids found (may be zero) */ static bool find_jobids_from_mediaid_list(JCR *jcr, idpkt *ids, const char *type) { bool ok = false; POOL_MEM query(PM_MESSAGE); Mmsg(query, sql_jobids_from_mediaid, ids->list); ids->count = 0; if (!db_sql_query(jcr->db, query.c_str(), unique_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 %s.\n"), type, jcr->get_ActionName(0)); } ok = true; bail_out: return ok; }
/* * Purge Job records from the database. For any Job which * is older than the retention period, we unconditionally delete * it and all File records for that Job. This is simple enough that no * temporary tables are needed. We simply make an in memory list of * the JobIds then delete the Job, Files, and JobMedia records in that list. */ static int purge_jobs_from_client(UAContext *ua, CLIENTRES *client) { struct del_ctx del; POOL_MEM query(PM_MESSAGE); CLIENT_DBR cr; char ed1[50]; memset(&cr, 0, sizeof(cr)); bstrncpy(cr.Name, client->name(), sizeof(cr.Name)); if (!db_create_client_record(ua->jcr, ua->db, &cr)) { return 0; } memset(&del, 0, sizeof(del)); del.max_ids = 1000; del.JobId = (JobId_t *)malloc(sizeof(JobId_t) * del.max_ids); del.PurgedFiles = (char *)malloc(del.max_ids); ua->info_msg(_("Begin purging jobs from Client \"%s\"\n"), cr.Name); Mmsg(query, select_jobs_from_client, edit_int64(cr.ClientId, ed1)); Dmsg1(150, "select sql=%s\n", query.c_str()); db_sql_query(ua->db, query.c_str(), job_delete_handler, (void *)&del); purge_job_list_from_catalog(ua, del); if (del.num_ids == 0) { ua->warning_msg(_("No Files found for client %s to purge from %s catalog.\n"), client->name(), client->catalog->name()); } else { ua->info_msg(_("%d Jobs for client %s purged from %s catalog.\n"), del.num_ids, client->name(), client->catalog->name()); } if (del.JobId) { free(del.JobId); } if (del.PurgedFiles) { free(del.PurgedFiles); } return 1; }
static void update_volinchanger(UAContext *ua, char *val, MEDIA_DBR *mr) { int InChanger; char ed1[50]; POOL_MEM query(PM_MESSAGE); if (!is_yesno(val, &InChanger)) { ua->error_msg(_("Invalid value. It must be yes or no.\n")); return; } Mmsg(query, "UPDATE Media SET InChanger=%d WHERE MediaId=%s", InChanger, edit_int64(mr->MediaId, ed1)); if (!db_sql_query(ua->db, query.c_str(), NULL, NULL)) { ua->error_msg("%s", db_strerror(ua->db)); } else { ua->info_msg(_("New InChanger flag is: %s\n"), InChanger==1?_("yes"):_("no")); } }
/* * Send current file list to FD * DIR -> FD : accurate files=xxxx * DIR -> FD : /path/to/file\0Lstat * DIR -> FD : /path/to/dir/\0Lstat * ... * DIR -> FD : EOD */ bool send_accurate_current_files(JCR *jcr) { POOL_MEM buf; if (!jcr->accurate || job_canceled(jcr) || jcr->get_JobLevel()==L_FULL) { return true; } POOLMEM *jobids = get_pool_memory(PM_FNAME); db_accurate_get_jobids(jcr, jcr->db, &jcr->jr, jobids); if (*jobids == 0) { free_pool_memory(jobids); Jmsg(jcr, M_FATAL, 0, _("Cannot find previous jobids.\n")); return false; } Jmsg(jcr, M_INFO, 0, _("Sending Accurate information.\n")); /* to be able to allocate the right size for htable */ POOLMEM *nb = get_pool_memory(PM_FNAME); *nb = 0; /* clear buffer */ Mmsg(buf, "SELECT sum(JobFiles) FROM Job WHERE JobId IN (%s)",jobids); db_sql_query(jcr->db, buf.c_str(), db_get_int_handler, nb); Dmsg2(200, "jobids=%s nb=%s\n", jobids, nb); jcr->file_bsock->fsend("accurate files=%s\n", nb); if (!db_open_batch_connexion(jcr, jcr->db)) { Jmsg0(jcr, M_FATAL, 0, "Can't get dedicate sql connexion"); return false; } db_get_file_list(jcr, jcr->db_batch, jobids, accurate_list_handler, (void *)jcr); /* TODO: close the batch connexion ? (can be used very soon) */ free_pool_memory(jobids); free_pool_memory(nb); jcr->file_bsock->signal(BNET_EOD); return true; }
static bool create_simple_name(JCR *jcr, MEDIA_DBR *mr, POOL_DBR *pr) { char num[20]; db_int64_ctx ctx; POOL_MEM query(PM_MESSAGE), name(PM_NAME); char ed1[50]; /* See if volume already exists */ mr->VolumeName[0] = 0; pm_strcpy(name, pr->LabelFormat); ctx.value = 0; Mmsg(query, "SELECT MAX(MediaId) FROM Media,Pool WHERE Pool.PoolId=%s", edit_int64(pr->PoolId, ed1)); if (!db_sql_query(jcr->db, query.c_str(), db_int64_handler, (void *)&ctx)) { Jmsg(jcr, M_WARNING, 0, _("SQL failed, but ignored. ERR=%s\n"), db_strerror(jcr->db)); ctx.value = pr->NumVols+1; } for (int i=(int)ctx.value+1; i<(int)ctx.value+100; i++) { MEDIA_DBR tmr; memset(&tmr, 0, sizeof(tmr)); sprintf(num, "%04d", i); bstrncpy(tmr.VolumeName, name.c_str(), sizeof(tmr.VolumeName)); bstrncat(tmr.VolumeName, num, sizeof(tmr.VolumeName)); if (db_get_media_record(jcr, jcr->db, &tmr)) { Jmsg(jcr, M_WARNING, 0, _("Wanted to create Volume \"%s\", but it already exists. Trying again.\n"), tmr.VolumeName); continue; } bstrncpy(mr->VolumeName, name.c_str(), sizeof(mr->VolumeName)); bstrncat(mr->VolumeName, num, sizeof(mr->VolumeName)); break; /* Got good name */ } if (mr->VolumeName[0] == 0) { Jmsg(jcr, M_ERROR, 0, _("Too many failures. Giving up creating Volume name.\n")); return false; } return true; }
/* * Delete Media record and all records that are associated with it. * Returns: false on error * true on success */ bool db_delete_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) { bool retval = false; db_lock(mdb); if (mr->MediaId == 0 && !db_get_media_record(jcr, mdb, mr)) { goto bail_out; } /* Do purge if not already purged */ if (!bstrcmp(mr->VolStatus, "Purged")) { /* Delete associated records */ do_media_purge(mdb, mr); } Mmsg(mdb->cmd, "DELETE FROM Media WHERE MediaId=%d", mr->MediaId); db_sql_query(mdb, mdb->cmd); retval = true; bail_out: db_unlock(mdb); return retval; }
/* * For a given path lookup the most recent backup in the catalog * to get the JobId and FileIndexes of all files in that directory. */ static bool insert_dir_into_findex_list(UAContext *ua, RESTORE_CTX *rx, char *dir, char *date) { strip_trailing_junk(dir); if (*rx->JobIds == 0) { ua->error_msg(_("No JobId specified cannot continue.\n")); return false; } else { Mmsg(rx->query, uar_jobid_fileindex_from_dir[db_get_type_index(ua->db)], rx->JobIds, dir, rx->ClientName); } rx->found = false; /* Find and insert jobid and File Index */ if (!db_sql_query(ua->db, rx->query, jobid_fileindex_handler, (void *)rx)) { ua->error_msg(_("Query failed: %s. ERR=%s\n"), rx->query, db_strerror(ua->db)); } if (!rx->found) { ua->error_msg(_("No database record found for: %s\n"), dir); return true; } return true; }
/* * This allows the message handler to operate on the database by using a pointer * to this function. The pointer is needed because the other daemons do not have * access to the database. If the pointer is not defined (other daemons), then * writing the database is disabled. */ static bool dir_db_log_insert(JCR *jcr, utime_t mtime, char *msg) { int length; char ed1[50]; char dt[MAX_TIME_LENGTH]; POOL_MEM query(PM_MESSAGE), esc_msg(PM_MESSAGE); if (!jcr || !jcr->db || !jcr->db->is_connected()) { return false; } length = strlen(msg) + 1; esc_msg.check_size(length * 2 + 1); db_escape_string(jcr, jcr->db, esc_msg.c_str(), msg, length); bstrutime(dt, sizeof(dt), mtime); Mmsg(query, "INSERT INTO Log (JobId, Time, LogText) VALUES (%s,'%s','%s')", edit_int64(jcr->JobId, ed1), dt, esc_msg.c_str()); return db_sql_query(jcr->db, query.c_str()); }
static void update_volstatus(UAContext *ua, const char *val, MEDIA_DBR *mr) { POOL_MEM query(PM_MESSAGE); const char *kw[] = { NT_("Append"), NT_("Archive"), NT_("Disabled"), NT_("Full"), NT_("Used"), NT_("Cleaning"), NT_("Recycle"), NT_("Read-Only"), NT_("Error"), NULL }; bool found = false; int i; for (i = 0; kw[i]; i++) { if (bstrcasecmp(val, kw[i])) { found = true; break; } } if (!found) { ua->error_msg(_("Invalid VolStatus specified: %s\n"), val); } else { char ed1[50]; bstrncpy(mr->VolStatus, kw[i], sizeof(mr->VolStatus)); Mmsg(query, "UPDATE Media SET VolStatus='%s' WHERE MediaId=%s", mr->VolStatus, edit_int64(mr->MediaId,ed1)); if (!db_sql_query(ua->db, query.c_str())) { ua->error_msg("%s", db_strerror(ua->db)); } else { ua->info_msg(_("New Volume status is: %s\n"), mr->VolStatus); } } }