/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-2010 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.
This program is Free Software; you can redistribute it and/or
- modify it under the terms of version two of the GNU General Public
+ modify it under the terms of version three of the GNU Affero General Public
License as published by the Free Software Foundation and included
in the file LICENSE.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Affero General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Bacula® is a registered trademark of John Walker.
+ Bacula® is a registered trademark of Kern Sibbald.
The licensor of Bacula is the Free Software Foundation Europe
(FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
Switzerland, email:ftf@fsfeurope.org.
*
* Kern Sibbald, September MM
*
- * Version $Id$
*/
#include "bacula.h"
static int update_volume(UAContext *ua);
static bool update_pool(UAContext *ua);
static bool update_job(UAContext *ua);
+static bool update_stats(UAContext *ua);
/*
* Update a Pool Record in the database.
* changes pool info for volume
* update slots [scan=...]
* updates autochanger slots
+ * update stats [days=...]
+ * updates long term statistics
*/
int update_cmd(UAContext *ua, const char *cmd)
{
NT_("volume"), /* 1 */
NT_("pool"), /* 2 */
NT_("slots"), /* 3 */
- NT_("jobid"), /* 4 */
+ NT_("slot"), /* 4 */
+ NT_("jobid"), /* 5 */
+ NT_("stats"), /* 6 */
NULL};
if (!open_client_db(ua)) {
update_pool(ua);
return 1;
case 3:
+ case 4:
update_slots(ua);
return 1;
- case 4:
+ case 5:
update_job(ua);
return 1;
+ case 6:
+ update_stats(ua);
+ return 1;
default:
break;
}
add_prompt(ua, _("Volume parameters"));
add_prompt(ua, _("Pool from resource"));
add_prompt(ua, _("Slots from autochanger"));
+ add_prompt(ua, _("Long term statistics"));
switch (do_prompt(ua, _("item"), _("Choose catalog item to update"), NULL, 0)) {
case 0:
update_volume(ua);
case 2:
update_slots(ua);
break;
+ case 3:
+ update_stats(ua);
+ break;
default:
break;
}
ua->error_msg("%s", db_strerror(ua->db));
} else {
ua->info_msg(_("New Recycle flag is: %s\n"),
- mr->Recycle==1?_("yes"):_("no"));
+ recycle==1?_("yes"):_("no"));
}
}
ua->error_msg("%s", db_strerror(ua->db));
} else {
ua->info_msg(_("New InChanger flag is: %s\n"),
- mr->InChanger==1?_("yes"):_("no"));
+ InChanger==1?_("yes"):_("no"));
}
}
void update_vol_pool(UAContext *ua, char *val, MEDIA_DBR *mr, POOL_DBR *opr)
{
POOL_DBR pr;
- POOLMEM *query;
+ POOL_MEM query(PM_MESSAGE);
char ed1[50], ed2[50];
memset(&pr, 0, sizeof(pr));
mr->PoolId = pr.PoolId; /* set new PoolId */
/*
*/
- query = get_pool_memory(PM_MESSAGE);
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, NULL, NULL)) {
+ 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);
}
}
db_unlock(ua->db);
- free_pool_memory(query);
}
/* Modify the RecyclePool of a Volume */
void update_vol_recyclepool(UAContext *ua, char *val, MEDIA_DBR *mr)
{
POOL_DBR pr;
- POOLMEM *query;
- char ed1[50], ed2[50];
-
- 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 */
+ 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*");
+ }
- query = get_pool_memory(PM_MESSAGE);
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, NULL, NULL)) {
+ 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"), pr.Name);
+ ua->info_msg(_("New RecyclePool is: %s\n"), poolname);
}
db_unlock(ua->db);
- free_pool_memory(query);
}
/*
* Refresh the Volume information from the Pool record
* for all Volumes
*/
-static void update_all_vols_from_pool(UAContext *ua)
+static void update_all_vols_from_pool(UAContext *ua, const char *pool_name)
{
POOL_DBR pr;
MEDIA_DBR mr;
memset(&pr, 0, sizeof(pr));
memset(&mr, 0, sizeof(mr));
+
+ bstrncpy(pr.Name, pool_name, sizeof(pr.Name));
if (!get_pool_dbr(ua, &pr)) {
return;
}
if (!db_update_media_defaults(ua->jcr, ua->db, &mr)) {
ua->error_msg(_("Error updating Volume records: ERR=%s"), db_strerror(ua->db));
} else {
- ua->info_msg(_("All Volume defaults updated from Pool record.\n"));
+ ua->info_msg(_("All Volume defaults updated from \"%s\" Pool record.\n"),
+ pr.Name);
}
}
+static void update_all_vols(UAContext *ua)
+{
+ int i, num_pools;
+ uint32_t *ids;
+ POOL_DBR pr;
+ MEDIA_DBR mr;
+
+ memset(&pr, 0, sizeof(pr));
+ memset(&mr, 0, sizeof(mr));
+
+ if (!db_get_pool_ids(ua->jcr, ua->db, &num_pools, &ids)) {
+ ua->error_msg(_("Error obtaining pool ids. ERR=%s\n"), db_strerror(ua->db));
+ return;
+ }
+
+ for (i=0; i<num_pools; i++) {
+ pr.PoolId = ids[i];
+ if (!db_get_pool_record(ua->jcr, ua->db, &pr)) { /* ***FIXME*** use acl? */
+ ua->warning_msg(_("Updating all pools, but skipped PoolId=%d. ERR=%s\n"), db_strerror(ua->db));
+ continue;
+ }
+
+ set_pool_dbr_defaults_in_media_dbr(&mr, &pr);
+ mr.PoolId = pr.PoolId;
+
+ if (!db_update_media_defaults(ua->jcr, ua->db, &mr)) {
+ ua->error_msg(_("Error updating Volume records: ERR=%s"), db_strerror(ua->db));
+ } else {
+ ua->info_msg(_("All Volume defaults updated from \"%s\" Pool record.\n"),
+ pr.Name);
+ }
+ }
+
+ free(ids);
+}
+
static void update_volenabled(UAContext *ua, char *val, MEDIA_DBR *mr)
{
mr->Enabled = get_enabled(ua, val);
return;
}
if (!db_update_media_record(ua->jcr, ua->db, mr)) {
- ua->error_msg(_("Error updating media record Enabled: ERR=%s"), db_strerror(ua->db));
+ ua->error_msg(_("Error updating media record Enabled: ERR=%s"),
+ db_strerror(ua->db));
} else {
ua->info_msg(_("New Enabled is: %d\n"), mr->Enabled);
}
}
-
+static void update_vol_actiononpurge(UAContext *ua, char *val, MEDIA_DBR *mr)
+{
+ POOL_MEM ret;
+ if (strcasecmp(val, "truncate") == 0) {
+ mr->ActionOnPurge = ON_PURGE_TRUNCATE;
+ } else {
+ mr->ActionOnPurge = 0;
+ }
+
+ if (!db_update_media_record(ua->jcr, ua->db, mr)) {
+ ua->error_msg(_("Error updating media record ActionOnPurge: ERR=%s"),
+ db_strerror(ua->db));
+ } else {
+ ua->info_msg(_("New ActionOnPurge is: %s\n"),
+ action_on_purge_to_string(mr->ActionOnPurge, ret));
+ }
+}
/*
* Update a media record -- allows you to change the
static int update_volume(UAContext *ua)
{
MEDIA_DBR mr;
+ POOL *pool;
POOL_DBR pr;
POOLMEM *query;
+ POOL_MEM ret;
+ char buf[1000];
char ed1[130];
bool done = false;
int i;
NT_("AllFromPool"), /* 11 !!! see below !!! */
NT_("Enabled"), /* 12 */
NT_("RecyclePool"), /* 13 */
+ NT_("ActionOnPurge"), /* 14 */
NULL };
#define AllFromPool 11 /* keep this updated with above */
for (i=0; kw[i]; i++) {
int j;
POOL_DBR pr;
+
if ((j=find_arg_with_value(ua, kw[i])) > 0) {
/* If all from pool don't select a media record */
if (i != AllFromPool && !select_media_dbr(ua, &mr)) {
update_vol_from_pool(ua, &mr);
return 1;
case 11:
- update_all_vols_from_pool(ua);
+ update_all_vols_from_pool(ua, ua->argv[j]);
return 1;
case 12:
update_volenabled(ua, ua->argv[j], &mr);
case 13:
update_vol_recyclepool(ua, ua->argv[j], &mr);
break;
+ case 14:
+ update_vol_actiononpurge(ua, ua->argv[j], &mr);
+ break;
}
done = true;
}
}
+ /* Allow user to simply update all volumes */
+ if (find_arg(ua, NT_("fromallpools")) > 0) {
+ update_all_vols(ua);
+ return 1;
+ }
+
for ( ; !done; ) {
start_prompt(ua, _("Parameters to modify:\n"));
add_prompt(ua, _("Volume Status")); /* 0 */
add_prompt(ua, _("Pool")); /* 10 */
add_prompt(ua, _("Volume from Pool")); /* 11 */
add_prompt(ua, _("All Volumes from Pool")); /* 12 */
- add_prompt(ua, _("Enabled")), /* 13 */
- add_prompt(ua, _("RecyclePool")), /* 14 */
- add_prompt(ua, _("Done")); /* 15 */
+ add_prompt(ua, _("All Volumes from all Pools")); /* 13 */
+ add_prompt(ua, _("Enabled")), /* 14 */
+ add_prompt(ua, _("RecyclePool")), /* 15 */
+ add_prompt(ua, _("Action On Purge")), /* 16 */
+ add_prompt(ua, _("Done")); /* 17 */
i = do_prompt(ua, "", _("Select parameter to modify"), NULL, 0);
- /* For All Volumes from Pool and Done, we don't need a Volume record */
- if (i != 12 && i != 15) {
+ /* For All Volumes, All Volumes from Pool, and Done, we don't need
+ * a Volume record */
+ if ( i != 12 && i != 13 && i != 17) {
if (!select_media_dbr(ua, &mr)) { /* Get Volume record */
return 0;
}
case 8: /* InChanger */
ua->info_msg(_("Current InChanger flag is: %d\n"), mr.InChanger);
- if (!get_yesno(ua, _("Set InChanger flag? yes/no: "))) {
+ bsnprintf(buf, sizeof(buf), _("Set InChanger flag for Volume \"%s\": yes/no: "),
+ mr.VolumeName);
+ if (!get_yesno(ua, buf)) {
return 0;
}
mr.InChanger = ua->pint32_val;
VolFiles = ua->pint32_val;
if (VolFiles != (int)(mr.VolFiles + 1)) {
ua->warning_msg(_("Normally, you should only increase Volume Files by one!\n"));
- if (!get_yesno(ua, _("Continue? (yes/no): ")) || ua->pint32_val == 0) {
+ if (!get_yesno(ua, _("Increase Volume Files? (yes/no): ")) || ua->pint32_val == 0) {
break;
}
}
update_vol_from_pool(ua, &mr);
return 1;
case 12:
- update_all_vols_from_pool(ua);
+ pool = select_pool_resource(ua);
+ if (pool) {
+ update_all_vols_from_pool(ua, pool->name());
+ }
return 1;
case 13:
+ update_all_vols(ua);
+ return 1;
+
+ case 14:
ua->info_msg(_("Current Enabled is: %d\n"), mr.Enabled);
if (!get_cmd(ua, _("Enter new Enabled: "))) {
return 0;
update_volenabled(ua, ua->cmd, &mr);
break;
- case 14:
+ case 15:
memset(&pr, 0, sizeof(POOL_DBR));
pr.PoolId = mr.RecyclePoolId;
if (db_get_pool_record(ua->jcr, ua->db, &pr)) {
ua->info_msg(_("Current RecyclePool is: %s\n"), pr.Name);
} else {
- ua->warning_msg(_("No current RecyclePool\n"));
+ ua->info_msg(_("No current RecyclePool\n"));
}
- if (!get_cmd(ua, _("Enter new RecyclePool name: "))) {
+ if (!select_pool_dbr(ua, &pr, NT_("recyclepool"))) {
return 0;
}
- update_vol_recyclepool(ua, ua->cmd, &mr);
+ update_vol_recyclepool(ua, pr.Name, &mr);
return 1;
+ case 16:
+ pm_strcpy(ret, "");
+ ua->info_msg(_("Current ActionOnPurge is: %s\n"),
+ action_on_purge_to_string(mr.ActionOnPurge, ret));
+ if (!get_cmd(ua, _("Enter new ActionOnPurge (one of: Truncate, None): "))) {
+ return 0;
+ }
+
+ update_vol_actiononpurge(ua, ua->cmd, &mr);
+ break;
+
default: /* Done or error */
ua->info_msg(_("Selection terminated.\n"));
return 1;
return 1;
}
+/*
+ * Update long term statistics
+ */
+static bool update_stats(UAContext *ua)
+{
+ int i = find_arg_with_value(ua, NT_("days"));
+ utime_t since=0;
+
+ if (i >= 0) {
+ since = atoi(ua->argv[i]) * 24*60*60;
+ }
+
+ int nb = db_update_stats(ua->jcr, ua->db, since);
+ ua->info_msg(_("Updating %i job(s).\n"), nb);
+
+ return true;
+}
+
/*
* Update pool record -- pull info from current POOL resource
*/
}
set_pooldbr_from_poolres(&pr, pool, POOL_OP_UPDATE); /* update */
- set_pooldbr_recyclepoolid(ua->jcr, ua->db, &pr, pool);
+ set_pooldbr_references(ua->jcr, ua->db, &pr, pool);
id = db_update_pool_record(ua->jcr, ua->db, &pr);
if (id <= 0) {
return false;
}
delta_start = StartTime - jr.StartTime;
- Dmsg3(200, "ST=%d jr.ST=%d delta=%d\n", (time_t)StartTime,
- (time_t)jr.StartTime, (time_t)delta_start);
+ Dmsg3(200, "ST=%lld jr.ST=%lld delta=%lld\n", StartTime,
+ (utime_t)jr.StartTime, delta_start);
jr.StartTime = (time_t)StartTime;
jr.SchedTime += (time_t)delta_start;
jr.EndTime += (time_t)delta_start;