#define B_IBM_LABEL 2
/*
- * Actions on purge
+ * Actions on purge (bit mask)
*/
#define AOP_TRUNCATE 1
"INSERT INTO Pool (Name,NumVols,MaxVols,UseOnce,UseCatalog,"
"AcceptAnyVolume,AutoPrune,Recycle,VolRetention,VolUseDuration,"
"MaxVolJobs,MaxVolFiles,MaxVolBytes,PoolType,LabelType,LabelFormat,"
-"RecyclePoolId,ScratchPoolId) "
-"VALUES ('%s',%u,%u,%d,%d,%d,%d,%d,%s,%s,%u,%u,%s,'%s',%d,'%s',%s,%s)",
+"RecyclePoolId,ScratchPoolId,ActionOnPurge) "
+"VALUES ('%s',%u,%u,%d,%d,%d,%d,%d,%s,%s,%u,%u,%s,'%s',%d,'%s',%s,%s,%d)",
pr->Name,
pr->NumVols, pr->MaxVols,
pr->UseOnce, pr->UseCatalog,
edit_uint64(pr->MaxVolBytes, ed3),
pr->PoolType, pr->LabelType, pr->LabelFormat,
edit_int64(pr->RecyclePoolId,ed4),
- edit_int64(pr->ScratchPoolId,ed5));
+ edit_int64(pr->ScratchPoolId,ed5),
+ pr->ActionOnPurge
+ );
Dmsg1(200, "Create Pool: %s\n", mdb->cmd);
if (!INSERT_DB(jcr, mdb, mdb->cmd)) {
Mmsg2(&mdb->errmsg, _("Create db Pool record %s failed: ERR=%s\n"),
"VolCapacityBytes,Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,"
"VolStatus,Slot,VolBytes,InChanger,VolReadTime,VolWriteTime,VolParts,"
"EndFile,EndBlock,LabelType,StorageId,DeviceId,LocationId,"
-"ScratchPoolId,RecyclePoolId,Enabled)"
+"ScratchPoolId,RecyclePoolId,Enabled,ActionOnPurge)"
"VALUES ('%s','%s',0,%u,%s,%s,%d,%s,%s,%u,%u,'%s',%d,%s,%d,%s,%s,%d,0,0,%d,%s,"
-"%s,%s,%s,%s,%d)",
+"%s,%s,%s,%s,%d,%d)",
mr->VolumeName,
mr->MediaType, mr->PoolId,
edit_uint64(mr->MaxVolBytes,ed1),
edit_int64(mr->LocationId, ed10),
edit_int64(mr->ScratchPoolId, ed11),
edit_int64(mr->RecyclePoolId, ed12),
- mr->Enabled
+ mr->Enabled, mr->ActionOnPurge
);
db_lock(mdb);
if (mr->VolumeName[0]) {
Mmsg(mdb->cmd, "UPDATE Media SET "
- "Recycle=%d,VolRetention=%s,VolUseDuration=%s,"
+ "ActionOnPurge=%d, Recycle=%d,VolRetention=%s,VolUseDuration=%s,"
"MaxVolJobs=%u,MaxVolFiles=%u,MaxVolBytes=%s,RecyclePoolId=%s"
" WHERE VolumeName='%s'",
- mr->Recycle,edit_uint64(mr->VolRetention, ed1),
+ mr->ActionOnPurge, mr->Recycle,edit_uint64(mr->VolRetention, ed1),
edit_uint64(mr->VolUseDuration, ed2),
mr->MaxVolJobs, mr->MaxVolFiles,
edit_uint64(mr->MaxVolBytes, ed3),
mr->VolumeName);
} else {
Mmsg(mdb->cmd, "UPDATE Media SET "
- "Recycle=%d,VolRetention=%s,VolUseDuration=%s,"
+ "ActionOnPurge=%d, Recycle=%d,VolRetention=%s,VolUseDuration=%s,"
"MaxVolJobs=%u,MaxVolFiles=%u,MaxVolBytes=%s,RecyclePoolId=%s"
" WHERE PoolId=%s",
- mr->Recycle,edit_uint64(mr->VolRetention, ed1),
+ mr->ActionOnPurge, mr->Recycle,edit_uint64(mr->VolRetention, ed1),
edit_uint64(mr->VolUseDuration, ed2),
mr->MaxVolJobs, mr->MaxVolFiles,
edit_uint64(mr->MaxVolBytes, ed3),
static void store_actiononpurge(LEX *lc, RES_ITEM *item, int index, int pass)
{
- uint32_t *destination = (uint32_t*)item->value;
- lex_get_token(lc, T_NAME);
- printf("got token %s\n", lc->str);
- if (strcasecmp(lc->str, "truncate") == 0)
- *destination = (*destination) | AOP_TRUNCATE;
- else {
- scan_err2(lc, _("Expected one of: %s, got: %s"), "Truncate", lc->str);
- return;
- }
- scan_to_eol(lc);
- set_bit(index, res_all.hdr.item_present);
+ uint32_t *destination = (uint32_t*)item->value;
+ lex_get_token(lc, T_NAME);
+ if (strcasecmp(lc->str, "truncate") == 0) {
+ *destination = (*destination) | AOP_TRUNCATE;
+ } else {
+ scan_err2(lc, _("Expected one of: %s, got: %s"), "Truncate", lc->str);
+ return;
+ }
+ scan_to_eol(lc);
+ set_bit(index, res_all.hdr.item_present);
}
/*
if (mr->ActionOnPurge > 0) {
/* Send the command to truncate the volume after purge. If this feature
- * is disabled for the specific device, this will be a no-op. */
+ * is disabled for the specific device, this will be a no-op.
+ */
BSOCK *sd;
if ((sd=open_sd_bsock(ua)) != NULL) {
+ bash_spaces(mr->VolumeName);
sd->fsend("action_on_purge %s vol=%s action=%d",
ua->jcr->wstore->dev_name(),
mr->VolumeName,
mr->ActionOnPurge);
-
- while (sd->recv() >= 0)
+ unbash_spaces(mr->VolumeName);
+ while (sd->recv() >= 0) {
ua->send_msg("%s", sd->msg);
+ }
sd->signal(BNET_TERMINATE);
sd->close();
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)
{
- if (strcasecmp(val, "truncate") == 0)
- mr->ActionOnPurge = AOP_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: %d\n"), mr->ActionOnPurge);
- }
+ POOL_MEM ret;
+ if (strcasecmp(val, "truncate") == 0) {
+ mr->ActionOnPurge = AOP_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: %d\n"),
+ aop_to_str(mr->ActionOnPurge, ret));
+ }
}
/*
POOL *pool;
POOL_DBR pr;
POOLMEM *query;
+ POOL_MEM ret;
char buf[1000];
char ed1[130];
bool done = false;
return 1;
case 16:
- ua->info_msg(_("Current ActionOnPurge is: %d\n"), mr.ActionOnPurge);
+ pm_strcpy(ret, "");
+ ua->info_msg(_("Current ActionOnPurge is: %s\n"),
+ aop_to_str(mr.ActionOnPurge, ret));
if (!get_cmd(ua, _("Enter new ActionOnPurge: (one of: Truncate, None) "))) {
- return 0;
+ return 0;
}
update_vol_actiononpurge(ua, ua->cmd, &mr);
void jobstatus_to_ascii_gui (int JobStatus, char *msg, int maxlen);
int run_program (char *prog, int wait, POOLMEM *&results);
int run_program_full_output (char *prog, int wait, POOLMEM *&results);
+char * aop_to_str (int aop, POOL_MEM &ret);
const char * job_type_to_str (int type);
const char * job_status_to_str (int stat);
const char * job_level_to_str (int level);
return str;
}
+/* Convert ActionOnPurge to string (Truncate, Erase, Destroy)
+ */
+char *aop_to_str(int aop, POOL_MEM &ret)
+{
+ if (aop & AOP_TRUNCATE) {
+ pm_strcpy(ret, _("Truncate"));
+ }
+ if (!aop) {
+ pm_strcpy(ret, _("None"));
+ }
+ return ret.c_str();
+}
+
/*
* Convert Job Level into a string
*/
BSOCK *dir = jcr->dir_bsock;
DEVICE *dev;
DCR *dcr;
- int drive;
int action;
if (sscanf(dir->msg, "action_on_purge %127s vol=%s action=%d",
dir->fsend(_("3916 Error scanning action_on_purge command\n"));
goto done;
}
+ unbash_spaces(volumename.c_str());
- /* FIXME: autochanger, drive = 0? how can we avoid that? we only work on files */
+ /* FIXME: autochanger, drive = 0? how can we avoid that? we only work on
+ * files
+ */
if ((dcr = find_device(jcr, devname, 0)) == NULL) {
dir->fsend(_("3999 Device \"%s\" not found or could not be opened.\n"), devname.c_str());
goto done;
bstrncpy(dev->VolHdr.VolumeName, volumename.c_str(), sizeof(dev->VolHdr.VolumeName));
/* Re-write the label with the recycle flag */
- if (rewrite_volume_label(dcr, true))
+ if (rewrite_volume_label(dcr, true)) {
dir->fsend(_("3917 Volume recycled\n"));
- else dir->fsend(_("3918 Recycle failed\n"));
+ } else {
+ dir->fsend(_("3918 Recycle failed\n"));
+ }
done:
dir->signal(BNET_EOD);
$ENV{bin} = $bin = $ENV{bin} || "$cwd/bin";
$ENV{tmp} = $tmp = $ENV{tmp} || "$cwd/tmp";
- $ENV{src} = $src = $ENV{src} || "$cwd/scr";
+ $ENV{src} = $src = $ENV{src} || "$cwd/src";
$ENV{conf} = $conf = $ENV{conf} || $bin;
$ENV{scripts} = $scripts = $ENV{scripts} || $bin;
$ENV{tmpsrc} = $tmpsrc = $ENV{tmpsrc} || "$cwd/tmp/build";
--- /dev/null
+#!/bin/sh
+#
+#
+TestName="action-on-purge-test"
+JobName=AOP
+. scripts/functions
+
+cwd=`pwd`
+scripts/cleanup
+scripts/copy-test-confs
+
+echo $src > $tmp/file-list
+sed 's/Pool Type = Backup/Pool Type = Backup; ActionOnPurge = Truncate/' $conf/bacula-dir.conf > $tmp/1
+cp $tmp/1 $conf/bacula-dir.conf
+
+change_jobname CompressedTest $JobName
+start_test
+
+cat >tmp/bconcmds <<END_OF_DATA
+@$out /dev/null
+messages
+@$out $tmp/log1.out
+label storage=File volume=TestVolume001
+run job=$JobName yes
+wait
+messages
+@$out $tmp/log2.out
+restore where=${cwd}/tmp/bacula-restores select all storage=File done
+yes
+wait
+messages
+@# Test ActionOnPurge=Truncate Volume size should be small
+@$out $tmp/log3.out
+purge volume=TestVolume001
+messages
+show pool
+@$out $tmp/log4.out
+sql
+select VolumeName, ActionOnPurge FROM Media;
+select Name, ActionOnPurge FROM Pool;
+
+quit
+END_OF_DATA
+
+run_bacula
+check_for_zombie_jobs storage=File
+stop_bacula
+
+check_two_logs
+check_restore_diff
+
+perl -e "die 'Volume size too big' if (-s '$tmp/TestVolume001' > 4096)"
+if [ $? != 0 ]; then
+ print_debug `ls -l $tmp/TestVolume001`
+ bstat=2
+fi
+
+print_debug "Test if Pool record is ok"
+r=`awk '/Default/ { print $4 }' $tmp/log4.out`
+if [ "$r" != 1 ]; then
+ print_debug "ActionOnPurge on Pool record should be 1"
+ bstat=2
+fi
+
+print_debug "Test if Media record is ok"
+r=`awk '/TestVolume001/ { print $4 }' $tmp/log4.out`
+if [ "$r" != 1 ]; then
+ print_debug "ActionOnPurge on Media record should be 1"
+ bstat=2
+fi
+
+end_test