From ce96b86fcfb5c1c3af6ee643b5e16e1be71407bb Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Thu, 20 Nov 2003 10:07:36 +0000 Subject: [PATCH] Implement InChanger code + fix Volume ordering git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@811 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/kernstodo | 6 +----- bacula/src/cats/protos.h | 2 +- bacula/src/cats/sql_find.c | 26 +++++++++++++++------- bacula/src/cats/sql_get.c | 8 ++++--- bacula/src/dird/next_vol.c | 20 +++++++++++++---- bacula/src/dird/protos.h | 44 +++++++++++++++++++------------------- bacula/src/dird/recycle.c | 24 +++++++++++++++------ bacula/src/dird/ua_cmds.c | 2 +- bacula/src/version.h | 4 ++-- 9 files changed, 83 insertions(+), 53 deletions(-) diff --git a/bacula/kernstodo b/bacula/kernstodo index ad5eecdb11..47ee0b99e8 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -64,13 +64,9 @@ For 1.33 - Possibly up network buffers to 65K. - Keep last 5 or 10 completed jobs and show them in a similar list. - Make a Running Jobs: output similar to current Scheduled Jobs: -- Optimize fsf not to read. -- Use ioctl() fsf if it exists. Figure out where we are from - the mt_status command. Use slow fsf only if other does not work. -- Add flag to write only one EOF mark on the tape. -- Implement autochanger testing in btape "test" command. After 1.33: +- Don't continue Restore if no files selected. - Print warning message if FileId > 4 billion - do a "messages" before the first prompt in Console - Add a date and time stamp at the beginning of every line in the diff --git a/bacula/src/cats/protos.h b/bacula/src/cats/protos.h index 767492e635..b19cc606bd 100644 --- a/bacula/src/cats/protos.h +++ b/bacula/src/cats/protos.h @@ -62,7 +62,7 @@ int db_delete_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr); /* find.c */ int db_find_job_start_time(JCR *jcr, B_DB *mdb, JOB_DBR *jr, POOLMEM **stime); int db_find_last_jobid(JCR *jcr, B_DB *mdb, char *Name, JOB_DBR *jr); -int db_find_next_volume(JCR *jcr, B_DB *mdb, int index, MEDIA_DBR *mr); +int db_find_next_volume(JCR *jcr, B_DB *mdb, int index, bool InChanger, MEDIA_DBR *mr); /* get.c */ int db_get_pool_record(JCR *jcr, B_DB *db, POOL_DBR *pdbr); diff --git a/bacula/src/cats/sql_find.c b/bacula/src/cats/sql_find.c index 1dd40978de..5e24511966 100644 --- a/bacula/src/cats/sql_find.c +++ b/bacula/src/cats/sql_find.c @@ -214,7 +214,7 @@ db_find_last_jobid(JCR *jcr, B_DB *mdb, char *Name, JOB_DBR *jr) * numrows on success */ int -db_find_next_volume(JCR *jcr, B_DB *mdb, int item, MEDIA_DBR *mr) +db_find_next_volume(JCR *jcr, B_DB *mdb, int item, bool InChanger, MEDIA_DBR *mr) { SQL_ROW row; int numrows; @@ -232,13 +232,23 @@ db_find_next_volume(JCR *jcr, B_DB *mdb, int item, MEDIA_DBR *mr) item = 1; } else { /* Find next available volume */ - Mmsg(&mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks," - "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes," - "VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,Recycle,Slot," - "FirstWritten,LastWritten,VolStatus " - "FROM Media WHERE PoolId=%u AND MediaType='%s' AND VolStatus='%s' " - "ORDER BY LastWritten", - mr->PoolId, mr->MediaType, mr->VolStatus); + if (InChanger) { + Mmsg(&mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks," + "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes," + "VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,Recycle,Slot," + "FirstWritten,LastWritten,VolStatus " + "FROM Media WHERE PoolId=%u AND MediaType='%s' AND VolStatus='%s' " + "AND InChanger=1 ORDER BY LastWritten,MediaId", + mr->PoolId, mr->MediaType, mr->VolStatus); + } else { + Mmsg(&mdb->cmd, "SELECT MediaId,VolumeName,VolJobs,VolFiles,VolBlocks," + "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes," + "VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,Recycle,Slot," + "FirstWritten,LastWritten,VolStatus " + "FROM Media WHERE PoolId=%u AND MediaType='%s' AND VolStatus='%s' " + "ORDER BY LastWritten,MediaId", + mr->PoolId, mr->MediaType, mr->VolStatus); + } } if (!QUERY_DB(jcr, mdb, mdb->cmd)) { db_unlock(mdb); diff --git a/bacula/src/cats/sql_get.c b/bacula/src/cats/sql_get.c index 9609d8570a..29d28c8cac 100644 --- a/bacula/src/cats/sql_get.c +++ b/bacula/src/cats/sql_get.c @@ -308,7 +308,8 @@ int db_get_job_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr) * Returns: 0 on error or no Volumes found * number of volumes on success * Volumes are concatenated in VolumeNames - * separated by a vertical bar (|). + * separated by a vertical bar (|) in the order + * that they were written. * * Returns: number of volumes on success */ @@ -320,8 +321,9 @@ int db_get_job_volume_names(JCR *jcr, B_DB *mdb, uint32_t JobId, POOLMEM **Volum db_lock(mdb); Mmsg(&mdb->cmd, -"SELECT VolumeName FROM JobMedia,Media WHERE JobMedia.JobId=%u " -"AND JobMedia.MediaId=Media.MediaId GROUP BY VolumeName", JobId); + "SELECT VolumeName,JobMedia.VolIndex FROM JobMedia,Media WHERE " + "JobMedia.JobId=%u AND JobMedia.MediaId=Media.MediaId " + "GROUP BY VolumeName ORDER BY JobMedia.VolIndex", JobId); Dmsg1(130, "VolNam=%s\n", mdb->cmd); *VolumeNames[0] = 0; diff --git a/bacula/src/dird/next_vol.c b/bacula/src/dird/next_vol.c index 0213c3c2e1..1f00693d0d 100644 --- a/bacula/src/dird/next_vol.c +++ b/bacula/src/dird/next_vol.c @@ -44,10 +44,16 @@ int find_next_volume_for_append(JCR *jcr, MEDIA_DBR *mr, int create) { int retry = 0; bool ok; + bool InChanger; mr->PoolId = jcr->PoolId; bstrncpy(mr->MediaType, jcr->store->media_type, sizeof(mr->MediaType)); Dmsg2(120, "CatReq FindMedia: Id=%d, MediaType=%s\n", mr->PoolId, mr->MediaType); + /* + * If we are using an Autochanger, restrict Volume + * search to the Autochanger on the first pass + */ + InChanger = jcr->store->autochanger; /* * Find the Next Volume for Append */ @@ -57,20 +63,26 @@ int find_next_volume_for_append(JCR *jcr, MEDIA_DBR *mr, int create) /* * 1. Look for volume with "Append" status. */ - ok = db_find_next_volume(jcr, jcr->db, 1, mr); + ok = db_find_next_volume(jcr, jcr->db, 1, InChanger, mr); Dmsg2(100, "catreq after find_next_vol ok=%d FW=%d\n", ok, mr->FirstWritten); if (!ok) { /* * 2. Try finding a recycled volume */ - ok = find_recycled_volume(jcr, mr); + ok = find_recycled_volume(jcr, InChanger, mr); Dmsg2(100, "find_recycled_volume %d FW=%d\n", ok, mr->FirstWritten); if (!ok) { /* * 3. Try pruning Volumes */ prune_volumes(jcr); - ok = recycle_oldest_purged_volume(jcr, mr); + ok = recycle_oldest_purged_volume(jcr, InChanger, mr); + if (InChanger) { + InChanger = false; + if (!ok) { + continue; /* retry again accepting any volume */ + } + } Dmsg2(200, "find_recycled_volume2 %d FW=%d\n", ok, mr->FirstWritten); if (!ok && create) { /* @@ -88,7 +100,7 @@ int find_next_volume_for_append(JCR *jcr, MEDIA_DBR *mr, int create) Dmsg2(200, "No next volume found. PurgeOldest=%d\n RecyleOldest=%d", jcr->pool->purge_oldest_volume, jcr->pool->recycle_oldest_volume); /* Find oldest volume to recycle */ - ok = db_find_next_volume(jcr, jcr->db, -1, mr); + ok = db_find_next_volume(jcr, jcr->db, -1, InChanger, mr); Dmsg1(400, "Find oldest=%d\n", ok); if (ok) { UAContext *ua; diff --git a/bacula/src/dird/protos.h b/bacula/src/dird/protos.h index 30d0dd7ac6..f05b8c0cd0 100644 --- a/bacula/src/dird/protos.h +++ b/bacula/src/dird/protos.h @@ -33,9 +33,9 @@ extern int do_autoprune(JCR *jcr); extern int prune_volumes(JCR *jcr); /* autorecycle.c */ -extern int recycle_oldest_purged_volume(JCR *jcr, MEDIA_DBR *mr); +extern int recycle_oldest_purged_volume(JCR *jcr, bool InChanger, MEDIA_DBR *mr); extern int recycle_volume(JCR *jcr, MEDIA_DBR *mr); -extern int find_recycled_volume(JCR *jcr, MEDIA_DBR *mr); +extern int find_recycled_volume(JCR *jcr, bool InChanger, MEDIA_DBR *mr); /* backup.c */ extern int wait_for_job_termination(JCR *jcr); @@ -62,7 +62,7 @@ int variable_expansion(JCR *jcr, char *inp, POOLMEM **exp); /* fd_cmds.c */ extern int connect_to_file_daemon(JCR *jcr, int retry_interval, - int max_retry_time, int verbose); + int max_retry_time, int verbose); extern int send_include_list(JCR *jcr); extern int send_exclude_list(JCR *jcr); extern int send_bootstrap_file(JCR *jcr); @@ -70,7 +70,7 @@ extern int send_level_command(JCR *jcr); extern int get_attributes_and_put_in_catalog(JCR *jcr); extern int get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId); extern int put_file_into_catalog(JCR *jcr, long file_index, char *fname, - char *link, char *attr, int stream); + char *link, char *attr, int stream); extern void get_level_since_time(JCR *jcr, char *since, int since_len); extern int send_run_before_and_after_commands(JCR *jcr); @@ -93,7 +93,7 @@ extern void mount_request(JCR *jcr, BSOCK *bs, char *buf); /* msgchan.c */ extern int connect_to_storage_daemon(JCR *jcr, int retry_interval, - int max_retry_time, int verbose); + int max_retry_time, int verbose); extern int start_storage_daemon_job(JCR *jcr); extern int start_storage_daemon_message_thread(JCR *jcr); extern int bget_dirmsg(BSOCK *bs); @@ -140,28 +140,28 @@ UAContext *new_ua_context(JCR *jcr); void free_ua_context(UAContext *ua); /* ua_select.c */ -STORE *select_storage_resource(UAContext *ua); -JOB *select_job_resource(UAContext *ua); -JOB *select_restore_job_resource(UAContext *ua); -CLIENT *select_client_resource(UAContext *ua); +STORE *select_storage_resource(UAContext *ua); +JOB *select_job_resource(UAContext *ua); +JOB *select_restore_job_resource(UAContext *ua); +CLIENT *select_client_resource(UAContext *ua); FILESET *select_fileset_resource(UAContext *ua); -int select_pool_and_media_dbr(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr); -int select_media_dbr(UAContext *ua, MEDIA_DBR *mr); -int select_pool_dbr(UAContext *ua, POOL_DBR *pr); -int select_client_dbr(UAContext *ua, CLIENT_DBR *cr); - -void start_prompt(UAContext *ua, char *msg); -void add_prompt(UAContext *ua, char *prompt); -int do_prompt(UAContext *ua, char *automsg, char *msg, char *prompt, int max_prompt); -CAT *get_catalog_resource(UAContext *ua); +int select_pool_and_media_dbr(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr); +int select_media_dbr(UAContext *ua, MEDIA_DBR *mr); +int select_pool_dbr(UAContext *ua, POOL_DBR *pr); +int select_client_dbr(UAContext *ua, CLIENT_DBR *cr); + +void start_prompt(UAContext *ua, char *msg); +void add_prompt(UAContext *ua, char *prompt); +int do_prompt(UAContext *ua, char *automsg, char *msg, char *prompt, int max_prompt); +CAT *get_catalog_resource(UAContext *ua); STORE *get_storage_resource(UAContext *ua, int use_default); -int get_media_type(UAContext *ua, char *MediaType, int max_media); -int get_pool_dbr(UAContext *ua, POOL_DBR *pr); -int get_client_dbr(UAContext *ua, CLIENT_DBR *cr); +int get_media_type(UAContext *ua, char *MediaType, int max_media); +int get_pool_dbr(UAContext *ua, POOL_DBR *pr); +int get_client_dbr(UAContext *ua, CLIENT_DBR *cr); POOL *get_pool_resource(UAContext *ua); POOL *select_pool_resource(UAContext *ua); CLIENT *get_client_resource(UAContext *ua); -int get_job_dbr(UAContext *ua, JOB_DBR *jr); +int get_job_dbr(UAContext *ua, JOB_DBR *jr); int find_arg_keyword(UAContext *ua, char **list); int find_arg(UAContext *ua, char *keyword); diff --git a/bacula/src/dird/recycle.c b/bacula/src/dird/recycle.c index 9e5b4fce0e..2b6006f257 100644 --- a/bacula/src/dird/recycle.c +++ b/bacula/src/dird/recycle.c @@ -55,10 +55,10 @@ static int oldest_handler(void *ctx, int num_fields, char **row) /* Forward referenced functions */ -int find_recycled_volume(JCR *jcr, MEDIA_DBR *mr) +int find_recycled_volume(JCR *jcr, bool InChanger, MEDIA_DBR *mr) { - strcpy(mr->VolStatus, "Recycle"); - if (db_find_next_volume(jcr, jcr->db, 1, mr)) { + bstrncpy(mr->VolStatus, "Recycle", sizeof(mr->VolStatus)); + if (db_find_next_volume(jcr, jcr->db, 1, InChanger, mr)) { jcr->MediaId = mr->MediaId; Dmsg1(20, "Find_next_vol MediaId=%d\n", jcr->MediaId); pm_strcpy(&jcr->VolumeName, mr->VolumeName); @@ -71,19 +71,29 @@ int find_recycled_volume(JCR *jcr, MEDIA_DBR *mr) /* * Look for oldest Purged volume */ -int recycle_oldest_purged_volume(JCR *jcr, MEDIA_DBR *mr) +int recycle_oldest_purged_volume(JCR *jcr, bool InChanger, MEDIA_DBR *mr) { struct s_oldest_ctx oldest; POOLMEM *query = get_pool_memory(PM_EMSG); - char *select = - "SELECT MediaId, LastWritten FROM Media " + char *select1 = + "SELECT MediaId,LastWritten FROM Media " + "WHERE PoolId=%u AND Recycle=1 AND VolStatus=\"Purged\" " + "AND MediaType=\"%s\" AND InChanger=1"; + char *select2 = + "SELECT MediaId,LastWritten FROM Media " "WHERE PoolId=%u AND Recycle=1 AND VolStatus=\"Purged\" " "AND MediaType=\"%s\""; + Dmsg0(100, "Enter recycle_oldest_purged_volume\n"); oldest.MediaId = 0; bstrncpy(oldest.LastWritten, "9999-99-99 99:99:99", sizeof(oldest.LastWritten)); - Mmsg(&query, select, mr->PoolId, mr->MediaType); + if (InChanger) { + Mmsg(&query, select1, mr->PoolId, mr->MediaType); + } else { + Mmsg(&query, select2, mr->PoolId, mr->MediaType); + } + if (!db_sql_query(jcr->db, query, oldest_handler, (void *)&oldest)) { Jmsg(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db)); Dmsg0(100, "Exit 0 recycle_oldest_purged_volume query\n"); diff --git a/bacula/src/dird/ua_cmds.c b/bacula/src/dird/ua_cmds.c index c94fa5a253..45f62fd5ec 100644 --- a/bacula/src/dird/ua_cmds.c +++ b/bacula/src/dird/ua_cmds.c @@ -95,7 +95,7 @@ static struct cmdstruct commands[] = { { N_("estimate"), estimate_cmd, _("performs FileSet estimate, listing gives full listing")}, { N_("exit"), quit_cmd, _("exit = quit")}, { N_("help"), help_cmd, _("print this command")}, - { N_("list"), list_cmd, _("list [pools | jobs | jobtotals | media | files job=]; from catalog")}, + { N_("list"), list_cmd, _("list [pools | jobs | jobtotals | media | files jobid=]; from catalog")}, { N_("label"), label_cmd, _("label a tape")}, { N_("llist"), llist_cmd, _("full or long list like list command")}, { N_("messages"), messagescmd, _("messages")}, diff --git a/bacula/src/version.h b/bacula/src/version.h index 2a8b2205c5..2c7f9eb13b 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -2,8 +2,8 @@ #undef VERSION #define VERSION "1.33" #define VSTRING "1" -#define BDATE "18 Nov 2003" -#define LSMDATE "18Nov03" +#define BDATE "20 Nov 2003" +#define LSMDATE "20Nov03" /* Debug flags */ #undef DEBUG -- 2.39.5