/* * 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; }
/* * Find last failed job since given start-time * it must be either Full or Diff. * * Returns: false on failure * true on success, jr is unchanged and stime unchanged * level returned in JobLevel */ bool db_find_failed_job_since(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM *stime, int &JobLevel) { SQL_ROW row; char ed1[50], ed2[50]; db_lock(mdb); /* Differential is since last Full backup */ Mmsg(mdb->cmd, "SELECT Level FROM Job WHERE JobStatus!='T' AND Type='%c' AND " "Level IN ('%c','%c') AND Name='%s' AND ClientId=%s " "AND FileSetId=%s AND StartTime>'%s' " "ORDER BY StartTime DESC LIMIT 1", jr->JobType, L_FULL, L_DIFFERENTIAL, jr->Name, edit_int64(jr->ClientId, ed1), edit_int64(jr->FileSetId, ed2), stime); if (!QUERY_DB(jcr, mdb, mdb->cmd)) { db_unlock(mdb); return false; } if ((row = sql_fetch_row(mdb)) == NULL) { sql_free_result(mdb); db_unlock(mdb); return false; } JobLevel = (int)*row[0]; sql_free_result(mdb); db_unlock(mdb); return true; }
/* * Update Client record * Returns: 0 on failure * 1 on success */ int db_update_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cr) { int stat; char ed1[50], ed2[50]; char esc_name[MAX_ESCAPE_NAME_LENGTH]; char esc_uname[MAX_ESCAPE_NAME_LENGTH]; CLIENT_DBR tcr; db_lock(mdb); memcpy(&tcr, cr, sizeof(tcr)); if (!db_create_client_record(jcr, mdb, &tcr)) { db_unlock(mdb); return 0; } mdb->db_escape_string(jcr, esc_name, cr->Name, strlen(cr->Name)); mdb->db_escape_string(jcr, esc_uname, cr->Uname, strlen(cr->Uname)); Mmsg(mdb->cmd, "UPDATE Client SET AutoPrune=%d,FileRetention=%s,JobRetention=%s," "Uname='%s' WHERE Name='%s'", cr->AutoPrune, edit_uint64(cr->FileRetention, ed1), edit_uint64(cr->JobRetention, ed2), esc_uname, esc_name); stat = UPDATE_DB(jcr, mdb, mdb->cmd); db_unlock(mdb); return stat; }
/* * Find JobId of last job that ran. E.g. for * VERIFY_CATALOG we want the JobId of the last INIT. * For VERIFY_VOLUME_TO_CATALOG, we want the JobId of the last Job. * * Returns: true on success * false on failure */ bool db_find_last_jobid(JCR *jcr, B_DB *mdb, const char *Name, JOB_DBR *jr) { SQL_ROW row; char ed1[50]; /* Find last full */ db_lock(mdb); Dmsg2(100, "JobLevel=%d JobType=%d\n", jr->JobLevel, jr->JobType); if (jr->JobLevel == L_VERIFY_CATALOG) { Mmsg(mdb->cmd, "SELECT JobId FROM Job WHERE Type='V' AND Level='%c' AND " " JobStatus IN ('T','W') AND Name='%s' AND " "ClientId=%s ORDER BY StartTime DESC LIMIT 1", L_VERIFY_INIT, jr->Name, edit_int64(jr->ClientId, ed1)); } else if (jr->JobLevel == L_VERIFY_VOLUME_TO_CATALOG || jr->JobLevel == L_VERIFY_DISK_TO_CATALOG || jr->JobType == JT_BACKUP) { if (Name) { Mmsg(mdb->cmd, "SELECT JobId FROM Job WHERE Type='B' AND JobStatus IN ('T','W') AND " "Name='%s' ORDER BY StartTime DESC LIMIT 1", Name); } else { Mmsg(mdb->cmd, "SELECT JobId FROM Job WHERE Type='B' AND JobStatus IN ('T','W') AND " "ClientId=%s ORDER BY StartTime DESC LIMIT 1", edit_int64(jr->ClientId, ed1)); } } else { Mmsg1(&mdb->errmsg, _("Unknown Job level=%d\n"), jr->JobLevel); db_unlock(mdb); return false; } Dmsg1(100, "Query: %s\n", mdb->cmd); if (!QUERY_DB(jcr, mdb, mdb->cmd)) { db_unlock(mdb); return false; } if ((row = sql_fetch_row(mdb)) == NULL) { Mmsg1(&mdb->errmsg, _("No Job found for: %s.\n"), mdb->cmd); sql_free_result(mdb); db_unlock(mdb); return false; } jr->JobId = str_to_int64(row[0]); sql_free_result(mdb); Dmsg1(100, "db_get_last_jobid: got JobId=%d\n", jr->JobId); if (jr->JobId <= 0) { Mmsg1(&mdb->errmsg, _("No Job found for: %s\n"), mdb->cmd); db_unlock(mdb); return false; } db_unlock(mdb); return true; }
bool update_container_file(struct directory *directory, const char *name, const struct stat *st, const struct decoder_plugin *plugin) { if (plugin->container_scan == NULL) return false; db_lock(); struct directory *contdir = make_directory_if_modified(directory, name, st); if (contdir == NULL) { /* not modified */ db_unlock(); return true; } contdir->device = DEVICE_CONTAINER; db_unlock(); char *const pathname = map_directory_child_fs(directory, name); char *vtrack; unsigned int tnum = 0; while ((vtrack = plugin->container_scan(pathname, ++tnum)) != NULL) { struct song *song = song_file_new(vtrack, contdir); // shouldn't be necessary but it's there.. song->mtime = st->st_mtime; char *child_path_fs = map_directory_child_fs(contdir, vtrack); song->tag = tag_new(); decoder_plugin_scan_file(plugin, child_path_fs, &add_tag_handler, song->tag); g_free(child_path_fs); db_lock(); directory_add_song(contdir, song); db_unlock(); modified = true; g_message("added %s/%s", directory_get_path(directory), vtrack); g_free(vtrack); } g_free(pathname); if (tnum == 1) { db_lock(); delete_directory(contdir); db_unlock(); return false; } else return true; }
/* * Automatic Volume name creation using the LabelFormat * * The media record must have the PoolId filled in when * calling this routine. */ bool newVolume(JCR *jcr, MEDIA_DBR *mr) { POOL_DBR pr; memset(&pr, 0, sizeof(pr)); /* See if we can create a new Volume */ db_lock(jcr->db); pr.PoolId = mr->PoolId; if (!db_get_pool_record(jcr, jcr->db, &pr)) { goto bail_out; } if (pr.MaxVols == 0 || pr.NumVols < pr.MaxVols) { memset(mr, 0, sizeof(MEDIA_DBR)); set_pool_dbr_defaults_in_media_dbr(mr, &pr); jcr->VolumeName[0] = 0; bstrncpy(mr->MediaType, jcr->wstore->media_type, sizeof(mr->MediaType)); generate_job_event(jcr, "NewVolume"); /* return bool */ generate_plugin_event(jcr, bEventNewVolume); /* return void... */ if (jcr->VolumeName[0] && is_volume_name_legal(NULL, jcr->VolumeName)) { bstrncpy(mr->VolumeName, jcr->VolumeName, sizeof(mr->VolumeName)); /* Check for special characters */ } else if (pr.LabelFormat[0] && pr.LabelFormat[0] != '*') { if (is_volume_name_legal(NULL, pr.LabelFormat)) { /* No special characters, so apply simple algorithm */ if (!create_simple_name(jcr, mr, &pr)) { goto bail_out; } } else { /* try full substitution */ /* Found special characters, so try substitution */ if (!perform_full_name_substitution(jcr, mr, &pr)) { goto bail_out; } if (!is_volume_name_legal(NULL, mr->VolumeName)) { Jmsg(jcr, M_ERROR, 0, _("Illegal character in Volume name \"%s\"\n"), mr->VolumeName); goto bail_out; } } } else { goto bail_out; } pr.NumVols++; mr->Enabled = 1; if (db_create_media_record(jcr, jcr->db, mr) && db_update_pool_record(jcr, jcr->db, &pr)) { db_unlock(jcr->db); Jmsg(jcr, M_INFO, 0, _("Created new Volume \"%s\" in catalog.\n"), mr->VolumeName); Dmsg1(90, "Created new Volume=%s\n", mr->VolumeName); return true; } else { Jmsg(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db)); } } bail_out: db_unlock(jcr->db); return false; }
/* * Use pool and client specified by user to select jobs to prune * returns add_from string to add in FROM clause * add_where string to add in WHERE clause */ bool prune_set_filter(UAContext *ua, CLIENTRES *client, POOLRES *pool, utime_t period, POOL_MEM *add_from, POOL_MEM *add_where) { utime_t now; char ed1[50], ed2[MAX_ESCAPE_NAME_LENGTH]; POOL_MEM tmp(PM_MESSAGE); now = (utime_t)time(NULL); edit_int64(now - period, ed1); Dmsg3(150, "now=%lld period=%lld JobTDate=%s\n", now, period, ed1); Mmsg(tmp, " AND JobTDate < %s ", ed1); pm_strcat(*add_where, tmp.c_str()); db_lock(ua->db); if (client) { db_escape_string(ua->jcr, ua->db, ed2, client->name(), strlen(client->name())); Mmsg(tmp, " AND Client.Name = '%s' ", ed2); pm_strcat(*add_where, tmp.c_str()); pm_strcat(*add_from, " JOIN Client USING (ClientId) "); } if (pool) { db_escape_string(ua->jcr, ua->db, ed2, pool->name(), strlen(pool->name())); Mmsg(tmp, " AND Pool.Name = '%s' ", ed2); pm_strcat(*add_where, tmp.c_str()); /* Use ON() instead of USING for some old SQLite */ pm_strcat(*add_from, " JOIN Pool ON (Job.PoolId = Pool.PoolId) "); } Dmsg2(150, "f=%s w=%s\n", add_from->c_str(), add_where->c_str()); db_unlock(ua->db); return true; }
/* * Update the Job record at start of Job * * Returns: false on failure * true on success */ bool db_update_job_start_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr) { char dt[MAX_TIME_LENGTH]; time_t stime; struct tm tm; btime_t JobTDate; bool retval; char ed1[50], ed2[50], ed3[50], ed4[50], ed5[50]; stime = jr->StartTime; (void)localtime_r(&stime, &tm); strftime(dt, sizeof(dt), "%Y-%m-%d %H:%M:%S", &tm); JobTDate = (btime_t)stime; db_lock(mdb); Mmsg(mdb->cmd, "UPDATE Job SET JobStatus='%c',Level='%c',StartTime='%s'," "ClientId=%s,JobTDate=%s,PoolId=%s,FileSetId=%s WHERE JobId=%s", (char)(jcr->JobStatus), (char)(jr->JobLevel), dt, edit_int64(jr->ClientId, ed1), edit_uint64(JobTDate, ed2), edit_int64(jr->PoolId, ed3), edit_int64(jr->FileSetId, ed4), edit_int64(jr->JobId, ed5)); retval = UPDATE_DB(jcr, mdb, mdb->cmd); mdb->changes = 0; db_unlock(mdb); return retval; }
void db_list_client_records(JCR *jcr, B_DB *mdb, char *clientname, OUTPUT_FORMATTER *sendit, e_list_type type) { db_lock(mdb); POOL_MEM clientfilter(PM_MESSAGE); if (clientname) { clientfilter.bsprintf("WHERE Name = '%s'", clientname); } if (type == VERT_LIST) { Mmsg(mdb->cmd, "SELECT ClientId,Name,Uname,AutoPrune,FileRetention," "JobRetention " "FROM Client %s ORDER BY ClientId ", clientfilter.c_str()); } else { Mmsg(mdb->cmd, "SELECT ClientId,Name,FileRetention,JobRetention " "FROM Client %s ORDER BY ClientId", clientfilter.c_str()); } if (!QUERY_DB(jcr, mdb, mdb->cmd)) { goto bail_out; } sendit->array_start("clients"); list_result(jcr, mdb, sendit, type); sendit->array_end("clients"); sql_free_result(mdb); bail_out: db_unlock(mdb); }
bool db_update_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr) { bool retval; char ed1[50], ed2[50], ed3[50], ed4[50], ed5[50], ed6[50]; char esc[MAX_ESCAPE_NAME_LENGTH]; db_lock(mdb); mdb->db_escape_string(jcr, esc, pr->LabelFormat, strlen(pr->LabelFormat)); Mmsg(mdb->cmd, "SELECT count(*) from Media WHERE PoolId=%s", edit_int64(pr->PoolId, ed4)); pr->NumVols = get_sql_record_max(jcr, mdb); Dmsg1(400, "NumVols=%d\n", pr->NumVols); Mmsg(mdb->cmd, "UPDATE Pool SET NumVols=%u,MaxVols=%u,UseOnce=%d,UseCatalog=%d," "AcceptAnyVolume=%d,VolRetention='%s',VolUseDuration='%s'," "MaxVolJobs=%u,MaxVolFiles=%u,MaxVolBytes=%s,Recycle=%d," "AutoPrune=%d,LabelType=%d,LabelFormat='%s',RecyclePoolId=%s," "ScratchPoolId=%s,ActionOnPurge=%d WHERE PoolId=%s", pr->NumVols, pr->MaxVols, pr->UseOnce, pr->UseCatalog, pr->AcceptAnyVolume, edit_uint64(pr->VolRetention, ed1), edit_uint64(pr->VolUseDuration, ed2), pr->MaxVolJobs, pr->MaxVolFiles, edit_uint64(pr->MaxVolBytes, ed3), pr->Recycle, pr->AutoPrune, pr->LabelType, esc, edit_int64(pr->RecyclePoolId,ed5), edit_int64(pr->ScratchPoolId,ed6), pr->ActionOnPurge, ed4); retval = UPDATE_DB(jcr, mdb, mdb->cmd); db_unlock(mdb); return retval; }
bool db_list_sql_query(JCR *jcr, B_DB *mdb, const char *query, OUTPUT_FORMATTER *sendit, e_list_type type, const char *description, bool verbose) { bool retval = false; db_lock(mdb); if (!sql_query(mdb, query, QF_STORE_RESULT)) { Mmsg(mdb->errmsg, _("Query failed: %s\n"), sql_strerror(mdb)); if (verbose) { sendit->decoration(mdb->errmsg); } goto bail_out; } sendit->array_start(description); list_result(jcr, mdb, sendit, type); sendit->array_end(description); sql_free_result(mdb); retval = true; bail_out: db_unlock(mdb); return retval; }
/* 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); }
void db_list_client_records(JCR *jcr, B_DB *mdb, OUTPUT_FORMATTER *sendit, e_list_type type) { db_lock(mdb); if (type == VERT_LIST) { Mmsg(mdb->cmd, "SELECT ClientId,Name,Uname,AutoPrune,FileRetention," "JobRetention " "FROM Client ORDER BY ClientId"); } else { Mmsg(mdb->cmd, "SELECT ClientId,Name,FileRetention,JobRetention " "FROM Client ORDER BY ClientId"); } if (!QUERY_DB(jcr, mdb, mdb->cmd)) { goto bail_out; } sendit->object_start("clients"); list_result(jcr, mdb, sendit, type); sendit->object_end("clients"); sql_free_result(mdb); bail_out: db_unlock(mdb); }
/* * Prune a given Volume */ bool prune_volume(UAContext *ua, MEDIA_DBR *mr) { POOL_MEM query(PM_MESSAGE); struct del_ctx del; bool ok = false; int count; if (mr->Enabled == 2) { return false; /* Cannot prune archived volumes */ } memset(&del, 0, sizeof(del)); del.max_ids = 10000; del.JobId = (JobId_t *)malloc(sizeof(JobId_t) * del.max_ids); db_lock(ua->db); /* Prune only Volumes with status "Full", or "Used" */ if (strcmp(mr->VolStatus, "Full") == 0 || strcmp(mr->VolStatus, "Used") == 0) { Dmsg2(050, "get prune list MediaId=%d Volume %s\n", (int)mr->MediaId, mr->VolumeName); count = get_prune_list_for_volume(ua, mr, &del); Dmsg1(050, "Num pruned = %d\n", count); if (count != 0) { purge_job_list_from_catalog(ua, del); } ok = is_volume_purged(ua, mr); } db_unlock(ua->db); if (del.JobId) { free(del.JobId); } return ok; }
/* * List Job totals * */ void db_list_job_totals(JCR *jcr, B_DB *mdb, JOB_DBR *jr, OUTPUT_FORMATTER *sendit) { db_lock(mdb); /* List by Job */ Mmsg(mdb->cmd, "SELECT count(*) AS Jobs,sum(JobFiles) " "AS Files,sum(JobBytes) AS Bytes,Name AS Job FROM Job GROUP BY Name"); if (!QUERY_DB(jcr, mdb, mdb->cmd)) { goto bail_out; } list_result(jcr, mdb, sendit, HORZ_LIST); sql_free_result(mdb); /* Do Grand Total */ Mmsg(mdb->cmd, "SELECT count(*) AS Jobs,sum(JobFiles) " "AS Files,sum(JobBytes) As Bytes FROM Job"); if (!QUERY_DB(jcr, mdb, mdb->cmd)) { goto bail_out; } list_result(jcr, mdb, sendit, HORZ_LIST); sql_free_result(mdb); bail_out: db_unlock(mdb); }
/* * Find last failed job since given start-time * it must be either Full or Diff. * * Returns: false on failure * true on success, jr is unchanged and stime unchanged * level returned in JobLevel */ bool db_find_failed_job_since(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM *stime, int &JobLevel) { bool retval = false; SQL_ROW row; char ed1[50], ed2[50]; char esc_name[MAX_ESCAPE_NAME_LENGTH]; db_lock(mdb); mdb->db_escape_string(jcr, esc_name, jr->Name, strlen(jr->Name)); /* Differential is since last Full backup */ Mmsg(mdb->cmd, "SELECT Level FROM Job WHERE JobStatus NOT IN ('T','W') AND " "Type='%c' AND Level IN ('%c','%c') AND Name='%s' AND ClientId=%s " "AND FileSetId=%s AND StartTime>'%s' " "ORDER BY StartTime DESC LIMIT 1", jr->JobType, L_FULL, L_DIFFERENTIAL, esc_name, edit_int64(jr->ClientId, ed1), edit_int64(jr->FileSetId, ed2), stime); if (!QUERY_DB(jcr, mdb, mdb->cmd)) { goto bail_out; } if ((row = sql_fetch_row(mdb)) == NULL) { sql_free_result(mdb); goto bail_out; } JobLevel = (int)*row[0]; sql_free_result(mdb); retval = true; bail_out: db_unlock(mdb); return retval; }
/* 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); }
/* * Set the inchanger flag to zero for each slot marked in * the given slot_list. * * The vol_list passed here needs to be from an "autochanger listall" cmd. */ void update_inchanger_for_export(UAContext *ua, STORERES *store, dlist *vol_list, char *slot_list) { vol_list_t *vl; MEDIA_DBR mr; if (!open_client_db(ua)) { return; } /* * Walk through the list updating the media records */ foreach_dlist(vl, vol_list) { /* * We are only interested in normal slots. */ switch (vl->Type) { case slot_type_normal: break; default: continue; } /* * Only update entries of slots marked in the slot_list. */ if (!bit_is_set(vl->Slot - 1, slot_list)) { continue; } /* * Set InChanger to zero for this Slot */ memset(&mr, 0, sizeof(mr)); mr.Slot = vl->Slot; mr.InChanger = 1; mr.MediaId = 0; /* Get by VolumeName */ if (vl->VolName) { bstrncpy(mr.VolumeName, vl->VolName, sizeof(mr.VolumeName)); } else { mr.VolumeName[0] = 0; } set_storageid_in_mr(store, &mr); Dmsg4(100, "Before make unique: Vol=%s slot=%d inchanger=%d sid=%d\n", mr.VolumeName, mr.Slot, mr.InChanger, mr.StorageId); db_lock(ua->db); /* * Set InChanger to zero for this Slot */ db_make_inchanger_unique(ua->jcr, ua->db, &mr); db_unlock(ua->db); Dmsg4(100, "After make unique: Vol=%s slot=%d inchanger=%d sid=%d\n", mr.VolumeName, mr.Slot, mr.InChanger, mr.StorageId); } return; }
/* * If VolumeName is non-zero, list the record for that Volume * otherwise, list the Volumes in the Pool specified by PoolId */ void db_list_media_records(JCR *jcr, B_DB *mdb, MEDIA_DBR *mdbr, OUTPUT_FORMATTER *sendit, e_list_type type) { char ed1[50]; char esc[MAX_ESCAPE_NAME_LENGTH]; db_lock(mdb); mdb->db_escape_string(jcr, esc, mdbr->VolumeName, strlen(mdbr->VolumeName)); if (type == VERT_LIST) { if (mdbr->VolumeName[0] != 0) { Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,Slot,PoolId," "MediaType,FirstWritten,LastWritten,LabelDate,VolJobs," "VolFiles,VolBlocks,VolMounts,VolBytes,VolErrors,VolWrites," "VolCapacityBytes,VolStatus,Enabled,Recycle,VolRetention," "VolUseDuration,MaxVolJobs,MaxVolFiles,MaxVolBytes,InChanger," "EndFile,EndBlock,LabelType,StorageId,DeviceId," "LocationId,RecycleCount,InitialWrite,ScratchPoolId,RecyclePoolId, " "Comment" " FROM Media WHERE Media.VolumeName='%s'", esc); } else { Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,Slot,PoolId," "MediaType,FirstWritten,LastWritten,LabelDate,VolJobs," "VolFiles,VolBlocks,VolMounts,VolBytes,VolErrors,VolWrites," "VolCapacityBytes,VolStatus,Enabled,Recycle,VolRetention," "VolUseDuration,MaxVolJobs,MaxVolFiles,MaxVolBytes,InChanger," "EndFile,EndBlock,LabelType,StorageId,DeviceId," "LocationId,RecycleCount,InitialWrite,ScratchPoolId,RecyclePoolId, " "Comment" " FROM Media WHERE Media.PoolId=%s ORDER BY MediaId", edit_int64(mdbr->PoolId, ed1)); } } else { if (mdbr->VolumeName[0] != 0) { Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolStatus,Enabled," "VolBytes,VolFiles,VolRetention,Recycle,Slot,InChanger,MediaType,LastWritten " "FROM Media WHERE Media.VolumeName='%s'", esc); } else { Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,VolStatus,Enabled," "VolBytes,VolFiles,VolRetention,Recycle,Slot,InChanger,MediaType,LastWritten " "FROM Media WHERE Media.PoolId=%s ORDER BY MediaId", edit_int64(mdbr->PoolId, ed1)); } } if (!QUERY_DB(jcr, mdb, mdb->cmd)) { goto bail_out; } sendit->object_start("media"); list_result(jcr, mdb, sendit, type); sendit->object_end("media"); sql_free_result(mdb); bail_out: db_unlock(mdb); }
/* * used for SELECT queries */ MYSQL_RES* db_select(char *query, ...) { va_list arglist; va_start(arglist, query); db_lock(); if (db_query_raw(query, arglist)) { va_end(arglist); db_unlock(); return NULL; } va_end(arglist); MYSQL_RES* ret = mysql_store_result(conn); db_unlock(); return ret; }
/* Mark the file record as being visited during database * verify compare. Stuff JobId into the MarkId field */ bool db_mark_file_record(JCR *jcr, B_DB *mdb, FileId_t FileId, JobId_t JobId) { bool retval; char ed1[50], ed2[50]; db_lock(mdb); Mmsg(mdb->cmd, "UPDATE File SET MarkId=%s WHERE FileId=%s", edit_int64(JobId, ed1), edit_int64(FileId, ed2)); retval = UPDATE_DB(jcr, mdb, mdb->cmd); db_unlock(mdb); return retval; }
/* * Delete Pool record, must also delete all associated * Media records. * * Returns: false on error * true on success * PoolId = number of Pools deleted (should be 1) * NumVols = number of Media records deleted */ bool db_delete_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr) { bool retval = false; SQL_ROW row; int num_rows; char esc[MAX_ESCAPE_NAME_LENGTH]; db_lock(mdb); mdb->db_escape_string(jcr, esc, pr->Name, strlen(pr->Name)); Mmsg(mdb->cmd, "SELECT PoolId FROM Pool WHERE Name='%s'", esc); Dmsg1(10, "selectpool: %s\n", mdb->cmd); pr->PoolId = pr->NumVols = 0; if (QUERY_DB(jcr, mdb, mdb->cmd)) { num_rows = sql_num_rows(mdb); if (num_rows == 0) { Mmsg(mdb->errmsg, _("No pool record %s exists\n"), pr->Name); sql_free_result(mdb); goto bail_out; } else if (num_rows != 1) { Mmsg(mdb->errmsg, _("Expecting one pool record, got %d\n"), num_rows); sql_free_result(mdb); goto bail_out; } if ((row = sql_fetch_row(mdb)) == NULL) { Mmsg1(mdb->errmsg, _("Error fetching row %s\n"), sql_strerror(mdb)); goto bail_out; } pr->PoolId = str_to_int64(row[0]); sql_free_result(mdb); } /* Delete Media owned by this pool */ Mmsg(mdb->cmd, "DELETE FROM Media WHERE Media.PoolId = %d", pr->PoolId); pr->NumVols = DELETE_DB(jcr, mdb, mdb->cmd); Dmsg1(200, "Deleted %d Media records\n", pr->NumVols); /* Delete Pool */ Mmsg(mdb->cmd, "DELETE FROM Pool WHERE Pool.PoolId = %d", pr->PoolId); pr->PoolId = DELETE_DB(jcr, mdb, mdb->cmd); Dmsg1(200, "Deleted %d Pool records\n", pr->PoolId); retval = true; bail_out: db_unlock(mdb); return retval; }
int log_get (logbase_t * base, long long rec, logrec_t * data) { int rc; if (base->fasync == 0) rc = db_shlock(base->fd); else rc = 0; if (rc >= 0) { rc = logi_get(base, rec, data); if (base->fasync == 0) db_unlock(base->fd); } else return IO_ERROR; return rc; }
bool db_update_storage_record(JCR *jcr, B_DB *mdb, STORAGE_DBR *sr) { bool retval; char ed1[50]; db_lock(mdb); Mmsg(mdb->cmd, "UPDATE Storage SET AutoChanger=%d WHERE StorageId=%s", sr->AutoChanger, edit_int64(sr->StorageId, ed1)); retval = UPDATE_DB(jcr, mdb, mdb->cmd); db_unlock(mdb); return retval; }
/* * used for insert and update queries * returns 0 for success */ int db_insert(char *query, ...) { va_list arglist; va_start(arglist, query); db_lock(); int res = db_query_raw(query, arglist); va_end(arglist); db_unlock(); return res; }
/* * Update the Job record at end of Job * * Returns: 0 on failure * 1 on success */ int db_update_job_end_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr) { char dt[MAX_TIME_LENGTH]; char rdt[MAX_TIME_LENGTH]; time_t ttime; struct tm tm; int stat; char ed1[30], ed2[30], ed3[50], ed4[50]; btime_t JobTDate; char PriorJobId[50]; if (jr->PriorJobId) { bstrncpy(PriorJobId, edit_int64(jr->PriorJobId, ed1), sizeof(PriorJobId)); } else { bstrncpy(PriorJobId, "0", sizeof(PriorJobId)); } ttime = jr->EndTime; (void)localtime_r(&ttime, &tm); strftime(dt, sizeof(dt), "%Y-%m-%d %H:%M:%S", &tm); if (jr->RealEndTime == 0) { jr->RealEndTime = jr->EndTime; } ttime = jr->RealEndTime; (void)localtime_r(&ttime, &tm); strftime(rdt, sizeof(rdt), "%Y-%m-%d %H:%M:%S", &tm); JobTDate = ttime; db_lock(mdb); Mmsg(mdb->cmd, "UPDATE Job SET JobStatus='%c',EndTime='%s'," "ClientId=%u,JobBytes=%s,ReadBytes=%s,JobFiles=%u,JobErrors=%u,VolSessionId=%u," "VolSessionTime=%u,PoolId=%u,FileSetId=%u,JobTDate=%s," "RealEndTime='%s',PriorJobId=%s,HasBase=%u,PurgedFiles=%u WHERE JobId=%s", (char)(jr->JobStatus), dt, jr->ClientId, edit_uint64(jr->JobBytes, ed1), edit_uint64(jr->ReadBytes, ed4), jr->JobFiles, jr->JobErrors, jr->VolSessionId, jr->VolSessionTime, jr->PoolId, jr->FileSetId, edit_uint64(JobTDate, ed2), rdt, PriorJobId, jr->HasBase, jr->PurgedFiles, edit_int64(jr->JobId, ed3)); stat = UPDATE_DB(jcr, mdb, mdb->cmd); db_unlock(mdb); return stat; }
int log_put (logbase_t * base, long long rec, logrec_t * data) { int rc; syslog(LOG_ERR, "log_put() requested :)"); if (base->fasync == 0) rc = db_exlock(base->fd); else rc = 0; if (rc >= 0) { rc = logi_put(base, rec, data); if (base->fasync == 0) db_unlock(base->fd); } else return IO_ERROR; return rc; }
/* * Find the last job start time for the specified JobLevel * * StartTime is returned in stime * * Returns: false on failure * true on success, jr is unchanged, but stime is set */ bool db_find_last_job_start_time(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM **stime, int JobLevel) { SQL_ROW row; char ed1[50], ed2[50]; db_lock(mdb); pm_strcpy(stime, "0000-00-00 00:00:00"); /* default */ Mmsg(mdb->cmd, "SELECT StartTime FROM Job WHERE JobStatus IN ('T','W') AND Type='%c' AND " "Level='%c' AND Name='%s' AND ClientId=%s AND FileSetId=%s " "ORDER BY StartTime DESC LIMIT 1", jr->JobType, JobLevel, jr->Name, edit_int64(jr->ClientId, ed1), edit_int64(jr->FileSetId, ed2)); if (!QUERY_DB(jcr, mdb, mdb->cmd)) { Mmsg2(&mdb->errmsg, _("Query error for start time request: ERR=%s\nCMD=%s\n"), sql_strerror(mdb), mdb->cmd); goto bail_out; } if ((row = sql_fetch_row(mdb)) == NULL) { sql_free_result(mdb); Mmsg(mdb->errmsg, _("No prior Full backup Job record found.\n")); goto bail_out; } Dmsg1(100, "Got start time: %s\n", row[0]); pm_strcpy(stime, row[0]); sql_free_result(mdb); db_unlock(mdb); return true; bail_out: db_unlock(mdb); return false; }
/* * Update Counters record * Returns: 0 on failure * 1 on success */ int db_update_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr) { char esc[MAX_ESCAPE_NAME_LENGTH]; db_lock(mdb); mdb->db_escape_string(jcr, esc, cr->Counter, strlen(cr->Counter)); Mmsg(mdb->cmd, "UPDATE Counters SET Counters.MinValue=%d,Counters.MaxValue=%d,CurrentValue=%d," "WrapCounter='%s' WHERE Counter='%s'", cr->MinValue, cr->MaxValue, cr->CurrentValue, cr->WrapCounter, esc); int stat = UPDATE_DB(jcr, mdb, mdb->cmd); db_unlock(mdb); return stat; }
/* 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; }