From bcfa8efda1940e20d62f85409287ba78e0fef0d6 Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Wed, 30 Sep 2009 18:17:34 +0200 Subject: [PATCH] Implement the ActionOnPurge setting for pools and individual volumes --- bacula/src/baconfig.h | 5 +++++ bacula/src/cats/cats.h | 2 ++ bacula/src/cats/sql_get.c | 7 +++++-- bacula/src/cats/sql_update.c | 10 ++++++---- bacula/src/dird/dird_conf.c | 22 ++++++++++++++++++++-- bacula/src/dird/dird_conf.h | 1 + bacula/src/dird/ua_cmds.c | 2 ++ bacula/src/dird/ua_update.c | 31 ++++++++++++++++++++++++++++--- 8 files changed, 69 insertions(+), 11 deletions(-) diff --git a/bacula/src/baconfig.h b/bacula/src/baconfig.h index 146a701862..73de474574 100644 --- a/bacula/src/baconfig.h +++ b/bacula/src/baconfig.h @@ -343,6 +343,11 @@ void InitWinAPIWrapper(); #define B_ANSI_LABEL 1 #define B_IBM_LABEL 2 +/* + * Actions on purge + */ +#define AOP_TRUNCATE 1 + /* Size of File Address stored in STREAM_SPARSE_DATA. Do NOT change! */ #define SPARSE_FADDR_SIZE (sizeof(uint64_t)) diff --git a/bacula/src/cats/cats.h b/bacula/src/cats/cats.h index 6b29b35315..1879050875 100644 --- a/bacula/src/cats/cats.h +++ b/bacula/src/cats/cats.h @@ -901,6 +901,7 @@ struct POOL_DBR { int32_t AcceptAnyVolume; /* set to accept any volume sequence */ int32_t AutoPrune; /* set to prune automatically */ int32_t Recycle; /* default Vol recycle flag */ + uint32_t ActionOnPurge; /* action on purge, e.g. truncate the disk volume */ utime_t VolRetention; /* retention period in seconds */ utime_t VolUseDuration; /* time in secs volume can be used */ uint32_t MaxVolJobs; /* Max Jobs on Volume */ @@ -976,6 +977,7 @@ struct MEDIA_DBR { uint64_t VolWriteTime; /* time spent writing volume */ utime_t VolRetention; /* Volume retention in seconds */ utime_t VolUseDuration; /* time in secs volume can be used */ + uint32_t ActionOnPurge; /* action on purge, e.g. truncate the disk volume */ uint32_t MaxVolJobs; /* Max Jobs on Volume */ uint32_t MaxVolFiles; /* Max files on Volume */ int32_t Recycle; /* recycle yes/no */ diff --git a/bacula/src/cats/sql_get.c b/bacula/src/cats/sql_get.c index e83359e3bb..255d7bbf27 100644 --- a/bacula/src/cats/sql_get.c +++ b/bacula/src/cats/sql_get.c @@ -608,13 +608,15 @@ bool db_get_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pdbr) Mmsg(mdb->cmd, "SELECT PoolId,Name,NumVols,MaxVols,UseOnce,UseCatalog,AcceptAnyVolume," "AutoPrune,Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles," -"MaxVolBytes,PoolType,LabelType,LabelFormat,RecyclePoolId,ScratchPoolId FROM Pool WHERE Pool.PoolId=%s", +"MaxVolBytes,PoolType,LabelType,LabelFormat,RecyclePoolId,ScratchPoolId," +"ActionOnPurge FROM Pool WHERE Pool.PoolId=%s", edit_int64(pdbr->PoolId, ed1)); } else { /* find by name */ Mmsg(mdb->cmd, "SELECT PoolId,Name,NumVols,MaxVols,UseOnce,UseCatalog,AcceptAnyVolume," "AutoPrune,Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles," -"MaxVolBytes,PoolType,LabelType,LabelFormat,RecyclePoolId,ScratchPoolId FROM Pool WHERE Pool.Name='%s'", +"MaxVolBytes,PoolType,LabelType,LabelFormat,RecyclePoolId,ScratchPoolId," +"ActionOnPurge FROM Pool WHERE Pool.Name='%s'", pdbr->Name); } if (QUERY_DB(jcr, mdb, mdb->cmd)) { @@ -648,6 +650,7 @@ bool db_get_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pdbr) bstrncpy(pdbr->LabelFormat, row[16]!=NULL?row[16]:"", sizeof(pdbr->LabelFormat)); pdbr->RecyclePoolId = str_to_int64(row[17]); pdbr->ScratchPoolId = str_to_int64(row[18]); + pdbr->ActionOnPurge = str_to_int32(row[19]); ok = true; } } diff --git a/bacula/src/cats/sql_update.c b/bacula/src/cats/sql_update.c index e659a18813..81293a3b9b 100644 --- a/bacula/src/cats/sql_update.c +++ b/bacula/src/cats/sql_update.c @@ -269,7 +269,7 @@ int db_update_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr) "AcceptAnyVolume=%d,VolRetention='%s',VolUseDuration='%s'," "MaxVolJobs=%u,MaxVolFiles=%u,MaxVolBytes=%s,Recycle=%d," "AutoPrune=%d,LabelType=%d,LabelFormat='%s',RecyclePoolId=%s," -"ScratchPoolId=%s WHERE PoolId=%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), @@ -277,7 +277,9 @@ int db_update_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr) edit_uint64(pr->MaxVolBytes, ed3), pr->Recycle, pr->AutoPrune, pr->LabelType, pr->LabelFormat, edit_int64(pr->RecyclePoolId,ed5), - edit_int64(pr->ScratchPoolId,ed6),ed4); + edit_int64(pr->ScratchPoolId,ed6), + pr->ActionOnPurge, + ed4); stat = UPDATE_DB(jcr, mdb, mdb->cmd); db_unlock(mdb); return stat; @@ -365,7 +367,7 @@ db_update_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) "Slot=%d,InChanger=%d,VolReadTime=%s,VolWriteTime=%s,VolParts=%d," "LabelType=%d,StorageId=%s,PoolId=%s,VolRetention=%s,VolUseDuration=%s," "MaxVolJobs=%d,MaxVolFiles=%d,Enabled=%d,LocationId=%s," - "ScratchPoolId=%s,RecyclePoolId=%s,RecycleCount=%d,Recycle=%d" + "ScratchPoolId=%s,RecyclePoolId=%s,RecycleCount=%d,Recycle=%d,ActionOnPurge=%d" " WHERE VolumeName='%s'", mr->VolJobs, mr->VolFiles, mr->VolBlocks, edit_uint64(mr->VolBytes, ed1), mr->VolMounts, mr->VolErrors, mr->VolWrites, @@ -383,7 +385,7 @@ db_update_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) mr->Enabled, edit_uint64(mr->LocationId, ed9), edit_uint64(mr->ScratchPoolId, ed10), edit_uint64(mr->RecyclePoolId, ed11), - mr->RecycleCount,mr->Recycle, + mr->RecycleCount,mr->Recycle, mr->ActionOnPurge, mr->VolumeName); Dmsg1(400, "%s\n", mdb->cmd); diff --git a/bacula/src/dird/dird_conf.c b/bacula/src/dird/dird_conf.c index 0517e4a9ab..4f6b33dc74 100644 --- a/bacula/src/dird/dird_conf.c +++ b/bacula/src/dird/dird_conf.c @@ -75,6 +75,7 @@ void store_level(LEX *lc, RES_ITEM *item, int index, int pass); void store_replace(LEX *lc, RES_ITEM *item, int index, int pass); void store_acl(LEX *lc, RES_ITEM *item, int index, int pass); void store_migtype(LEX *lc, RES_ITEM *item, int index, int pass); +static void store_actiononpurge(LEX *lc, RES_ITEM *item, int index, int pass); static void store_device(LEX *lc, RES_ITEM *item, int index, int pass); static void store_runscript(LEX *lc, RES_ITEM *item, int index, int pass); static void store_runscript_when(LEX *lc, RES_ITEM *item, int index, int pass); @@ -381,6 +382,7 @@ static RES_ITEM pool_items[] = { {"usecatalog", store_bool, ITEM(res_pool.use_catalog), 0, ITEM_DEFAULT, true}, {"usevolumeonce", store_bool, ITEM(res_pool.use_volume_once), 0, 0, 0}, {"purgeoldestvolume", store_bool, ITEM(res_pool.purge_oldest_volume), 0, 0, 0}, + {"actiononpurge", store_actiononpurge, ITEM(res_pool.action_on_purge), 0, 0, 0}, {"recycleoldestvolume", store_bool, ITEM(res_pool.recycle_oldest_volume), 0, 0, 0}, {"recyclecurrentvolume", store_bool, ITEM(res_pool.recycle_current_volume), 0, 0, 0}, {"maximumvolumes", store_pint32, ITEM(res_pool.max_volumes), 0, 0, 0}, @@ -939,9 +941,10 @@ next_run: NPRT(res->res_pool.label_format)); sendit(sock, _(" CleaningPrefix=%s LabelType=%d\n"), NPRT(res->res_pool.cleaning_prefix), res->res_pool.LabelType); - sendit(sock, _(" RecyleOldest=%d PurgeOldest=%d\n"), + sendit(sock, _(" RecyleOldest=%d PurgeOldest=%d ActionOnPurge=%d\n"), res->res_pool.recycle_oldest_volume, - res->res_pool.purge_oldest_volume); + res->res_pool.purge_oldest_volume, + res->res_pool.action_on_purge); sendit(sock, _(" MaxVolJobs=%d MaxVolFiles=%d MaxVolBytes=%s\n"), res->res_pool.MaxVolJobs, res->res_pool.MaxVolFiles, @@ -1596,6 +1599,21 @@ void save_resource(int type, RES_ITEM *items, int pass) } } +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); +} + /* * Store Device. Note, the resource is created upon the * first reference. The details of the resource are obtained diff --git a/bacula/src/dird/dird_conf.h b/bacula/src/dird/dird_conf.h index 55706ec6c4..9f398af3ae 100644 --- a/bacula/src/dird/dird_conf.h +++ b/bacula/src/dird/dird_conf.h @@ -562,6 +562,7 @@ public: bool recycle_current_volume; /* attempt recycle of current volume */ bool AutoPrune; /* default for pool auto prune */ bool Recycle; /* default for media recycle yes/no */ + uint32_t action_on_purge; /* action on purge, e.g. truncate the disk volume */ POOL *RecyclePool; /* RecyclePool destination when media is purged */ POOL *ScratchPool; /* ScratchPool source when requesting media */ alist *CopyPool; /* List of copy pools */ diff --git a/bacula/src/dird/ua_cmds.c b/bacula/src/dird/ua_cmds.c index 80fa7233e6..92c6298b12 100644 --- a/bacula/src/dird/ua_cmds.c +++ b/bacula/src/dird/ua_cmds.c @@ -231,6 +231,7 @@ void set_pool_dbr_defaults_in_media_dbr(MEDIA_DBR *mr, POOL_DBR *pr) mr->Recycle = pr->Recycle; mr->VolRetention = pr->VolRetention; mr->VolUseDuration = pr->VolUseDuration; + mr->ActionOnPurge = pr->ActionOnPurge; mr->RecyclePoolId = pr->RecyclePoolId; mr->MaxVolJobs = pr->MaxVolJobs; mr->MaxVolFiles = pr->MaxVolFiles; @@ -571,6 +572,7 @@ void set_pooldbr_from_poolres(POOL_DBR *pr, POOL *pool, e_pool_op op) pr->MaxVolFiles = pool->MaxVolFiles; pr->MaxVolBytes = pool->MaxVolBytes; pr->AutoPrune = pool->AutoPrune; + pr->ActionOnPurge = pool->action_on_purge; pr->Recycle = pool->Recycle; if (pool->label_format) { bstrncpy(pr->LabelFormat, pool->label_format, sizeof(pr->LabelFormat)); diff --git a/bacula/src/dird/ua_update.c b/bacula/src/dird/ua_update.c index ff0f94ad32..00f3902166 100644 --- a/bacula/src/dird/ua_update.c +++ b/bacula/src/dird/ua_update.c @@ -471,7 +471,18 @@ static void update_volenabled(UAContext *ua, char *val, MEDIA_DBR *mr) } } - +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); + } +} /* * Update a media record -- allows you to change the @@ -504,6 +515,7 @@ static int update_volume(UAContext *ua) NT_("AllFromPool"), /* 11 !!! see below !!! */ NT_("Enabled"), /* 12 */ NT_("RecyclePool"), /* 13 */ + NT_("ActionOnPurge"), /* 14 */ NULL }; #define AllFromPool 11 /* keep this updated with above */ @@ -566,6 +578,9 @@ static int update_volume(UAContext *ua) case 13: update_vol_recyclepool(ua, ua->argv[j], &mr); break; + case 14: + update_vol_actiononpurge(ua, ua->argv[j], &mr); + break; } done = true; } @@ -595,12 +610,13 @@ static int update_volume(UAContext *ua) add_prompt(ua, _("All Volumes from all Pools")); /* 13 */ add_prompt(ua, _("Enabled")), /* 14 */ add_prompt(ua, _("RecyclePool")), /* 15 */ - add_prompt(ua, _("Done")); /* 16 */ + 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, All Volumes from Pool, and Done, we don't need * a Volume record */ - if ( i != 12 && i != 13 && i != 16) { + if ( i != 12 && i != 13 && i != 17) { if (!select_media_dbr(ua, &mr)) { /* Get Volume record */ return 0; } @@ -791,6 +807,15 @@ static int update_volume(UAContext *ua) update_vol_recyclepool(ua, pr.Name, &mr); return 1; + case 16: + ua->info_msg(_("Current ActionOnPurge is: %d\n"), mr.ActionOnPurge); + 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; -- 2.39.5