From 7de2f5db87b33c49fe5e54f80f82f5fb8a75c4cd Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Mon, 21 Feb 2005 12:00:23 +0000 Subject: [PATCH] - Make clean remove old CVS files - Remove unnecessary image files from Latex directory - Implement remaining parts of Storage DB record and its use in the Director. - Implement FullMaxWaitTime, Differential Max Wait Time, and Incremental Max Wait time in Job resource. - Start work on SD Autochanger code. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@1837 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/Makefile.in | 1 + bacula/kernstodo | 22 ++++++--- bacula/src/cats/cats.h | 13 +++-- bacula/src/cats/protos.h | 1 + bacula/src/cats/sql_create.c | 86 +++++++++++++++++++-------------- bacula/src/cats/sql_get.c | 5 +- bacula/src/cats/sql_list.c | 4 +- bacula/src/cats/sql_update.c | 76 +++++++++++++++-------------- bacula/src/dird/catreq.c | 4 +- bacula/src/dird/dird.c | 6 ++- bacula/src/dird/dird.h | 2 +- bacula/src/dird/dird_conf.c | 8 ++- bacula/src/dird/dird_conf.h | 5 ++ bacula/src/dird/job.c | 26 +++++++--- bacula/src/dird/next_vol.c | 72 +++++++++++++-------------- bacula/src/dird/recycle.c | 2 +- bacula/src/dird/ua_cmds.c | 1 - bacula/src/dird/ua_label.c | 47 +++++++++--------- bacula/src/stored/stored_conf.c | 10 ++++ bacula/src/stored/stored_conf.h | 18 ++++--- bacula/src/version.h | 4 +- 21 files changed, 242 insertions(+), 171 deletions(-) diff --git a/bacula/Makefile.in b/bacula/Makefile.in index 3f805b3ad0..a5b99c1e03 100755 --- a/bacula/Makefile.in +++ b/bacula/Makefile.in @@ -182,6 +182,7 @@ clean: @$(RMF) *~ 1 2 3 core core.* config.guess console.log console.sum @$(RMF) examples/1 examples/2 examples/devices/1 examples/devices/2 @$(RMF) -r autom4te.cache + @find . -name .#* -exec $(RMF) {} \; # clean for distribution diff --git a/bacula/kernstodo b/bacula/kernstodo index ccd7730253..229c8bc80a 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -30,8 +30,18 @@ Suggestions for Preben: - Optimized bootstrap. For 1.37: -- Try to open a device on each Job if it was not opened - when the SD started. +- Add disk seeking on restore. +- Add Python writable variable for changing the Priority, + Client, Storage, JobStatus (error), ... +- SD Autochanger work + - Lock all devices when using changer script. + - Check if Volume is mounted on another device + - Find a free drive if Changer name used. +- SD Python + - Solicit Events +- FD Python + - Python script to save with Python, not save, save with Bacula. + - Python script to do backup. - Windows restore: data-fd: RestoreFiles.2004-12-07_15.56.42 Error: > ..\findlib\../../findlib/create_file.c:275 Could not open e:/: ERR=Der @@ -56,16 +66,12 @@ For 1.37: design. - Create a new GUI chapter explaining all the GUI programs. - Tell the "restore" user when browsing is no longer possible. -- Add disk seeking on restore. - Cancel command should include JobId in list of Jobs. - Require restore via the restore command or make a restore Job get the bootstrap file. -- Add dump of VolSessionId/Time and FileIndex with bls. - Make bootstrap file handle multiple MediaTypes (SD) - Add offline tape command to Bacula console. - Add performance testing hooks -- Add Python writable variable for changing the Priority, - Client, Storage, JobStatus (error), ... - Document that Bootstrap files can be written with cataloging turned off. - Look at adding full Volume and Pool information to a Volume @@ -1209,3 +1215,7 @@ Block Position: 0 - Implement Preben's suggestion to add File System Types = ext2, ext3 to FileSets, thus simplifying backup of *all* local partitions. +- Try to open a device on each Job if it was not opened + when the SD started. +- Add dump of VolSessionId/Time and FileIndex with bls. + diff --git a/bacula/src/cats/cats.h b/bacula/src/cats/cats.h index bcbffd5276..90f99df892 100644 --- a/bacula/src/cats/cats.h +++ b/bacula/src/cats/cats.h @@ -370,10 +370,10 @@ typedef struct s_db { typedef char **POSTGRESQL_ROW; typedef struct pg_field { - char *name; - int max_length; - unsigned int type; - unsigned int flags; // 1 == not null + char *name; + int max_length; + unsigned int type; + unsigned int flags; // 1 == not null } POSTGRESQL_FIELD; @@ -676,8 +676,10 @@ class STORAGE_DBR { public: DBId_t StorageId; char Name[MAX_NAME_LENGTH]; /* Device name */ - DBId_t MediaTypeId; /* MediaType */ int AutoChanger; /* Set if autochanger */ + + /* Not in database */ + bool created; /* set if created by db_create ... */ }; class MEDIATYPE_DBR { @@ -718,6 +720,7 @@ struct MEDIA_DBR { int32_t Recycle; /* recycle yes/no */ int32_t Slot; /* slot in changer */ int32_t InChanger; /* Volume currently in changer */ + DBId_t StorageId; /* Storage record Id */ uint32_t EndFile; /* Last file on volume */ uint32_t EndBlock; /* Last block on volume */ char VolStatus[20]; /* Volume status */ diff --git a/bacula/src/cats/protos.h b/bacula/src/cats/protos.h index 305679d1f6..0022b75d18 100644 --- a/bacula/src/cats/protos.h +++ b/bacula/src/cats/protos.h @@ -106,6 +106,7 @@ bool db_update_job_start_record(JCR *jcr, B_DB *db, JOB_DBR *jr); int db_update_job_end_record(JCR *jcr, B_DB *db, JOB_DBR *jr); int db_update_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cr); int db_update_pool_record(JCR *jcr, B_DB *db, POOL_DBR *pr); +bool db_update_storage_record(JCR *jcr, B_DB *mdb, STORAGE_DBR *sr); int db_update_media_record(JCR *jcr, B_DB *db, MEDIA_DBR *mr); int db_update_media_defaults(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr); int db_update_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr); diff --git a/bacula/src/cats/sql_create.c b/bacula/src/cats/sql_create.c index 1265d78a05..8fe07996aa 100644 --- a/bacula/src/cats/sql_create.c +++ b/bacula/src/cats/sql_create.c @@ -215,7 +215,7 @@ db_create_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr) bool db_create_device_record(JCR *jcr, B_DB *mdb, DEVICE_DBR *dr) { - bool stat; + bool ok; char ed1[30], ed2[30]; Dmsg0(200, "In create Device\n"); @@ -236,69 +236,81 @@ db_create_device_record(JCR *jcr, B_DB *mdb, DEVICE_DBR *dr) /* Must create it */ Mmsg(mdb->cmd, -"INSERT INTO Device (Name,MediaTypeId,StorageId) " -"VALUES ('%s',%s,%s)", +"INSERT INTO Device (Name,MediaTypeId,StorageId) VALUES ('%s',%s,%s)", dr->Name, edit_uint64(dr->MediaTypeId, ed1), - edit_uint64(dr->StorageId, ed2)); + edit_int64(dr->StorageId, ed2)); Dmsg1(200, "Create Device: %s\n", mdb->cmd); if (!INSERT_DB(jcr, mdb, mdb->cmd)) { Mmsg2(&mdb->errmsg, _("Create db Device record %s failed: ERR=%s\n"), mdb->cmd, sql_strerror(mdb)); dr->DeviceId = 0; - stat = false; + ok = false; } else { dr->DeviceId = sql_insert_id(mdb, _("Device")); - stat = true; + ok = true; } db_unlock(mdb); - return stat; + return ok; } + + /* - * Create Unique storage record + * Create a Unique record for Storage -- no duplicates * Returns: false on failure - * true on success + * true on success with id in sr->StorageId */ -bool -db_create_storage_record(JCR *jcr, B_DB *mdb, STORAGE_DBR *sr) +bool db_create_storage_record(JCR *jcr, B_DB *mdb, STORAGE_DBR *sr) { - bool stat; + SQL_ROW row; + bool ok; - Dmsg0(200, "In create storage\n"); db_lock(mdb); - Mmsg(mdb->cmd, "SELECT StorageId,Name FROM Storage WHERE Name='%s'", sr->Name); - Dmsg1(200, "selectstorage: %s\n", mdb->cmd); + Mmsg(mdb->cmd, "SELECT StorageId,AutoChanger FROM Storage WHERE Name='%s'", sr->Name); + sr->StorageId = 0; + sr->created = false; if (QUERY_DB(jcr, mdb, mdb->cmd)) { mdb->num_rows = sql_num_rows(mdb); - if (mdb->num_rows > 0) { - Mmsg1(&mdb->errmsg, _("Storage record %s already exists\n"), sr->Name); + /* If more than one, report error, but return first row */ + if (mdb->num_rows > 1) { + Mmsg1(&mdb->errmsg, _("More than one Storage record!: %d\n"), (int)(mdb->num_rows)); + Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); + } + if (mdb->num_rows >= 1) { + if ((row = sql_fetch_row(mdb)) == NULL) { + Mmsg1(&mdb->errmsg, _("error fetching Storage row: %s\n"), sql_strerror(mdb)); + Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); + sql_free_result(mdb); + db_unlock(mdb); + return false; + } + sr->StorageId = str_to_int64(row[0]); + sr->AutoChanger = atoi(row[1]); /* bool */ sql_free_result(mdb); db_unlock(mdb); - return false; + return true; } sql_free_result(mdb); } /* Must create it */ - Mmsg(mdb->cmd, -"INSERT INTO Storage (Name,AutoChanger) " -"VALUES ('%s',%d)", - sr->Name, - sr->AutoChanger); - Dmsg1(200, "Create storage: %s\n", mdb->cmd); + Mmsg(mdb->cmd, "INSERT INTO Storage (Name,AutoChanger)" + " VALUES ('%s',%d)", sr->Name, sr->AutoChanger); + if (!INSERT_DB(jcr, mdb, mdb->cmd)) { - Mmsg2(&mdb->errmsg, _("Create db storage record %s failed: ERR=%s\n"), + Mmsg2(&mdb->errmsg, _("Create DB Storage record %s failed. ERR=%s\n"), mdb->cmd, sql_strerror(mdb)); - sr->StorageId = 0; - stat = false; + Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg); + ok = false; } else { sr->StorageId = sql_insert_id(mdb, _("Storage")); - stat = true; + sr->created = true; + ok = true; } db_unlock(mdb); - return stat; + return ok; } @@ -349,8 +361,6 @@ db_create_mediatype_record(JCR *jcr, B_DB *mdb, MEDIATYPE_DBR *mr) } - - /* * Create Media record. VolumeName and non-zero Slot must be unique * @@ -361,7 +371,7 @@ int db_create_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) { int stat; - char ed1[30], ed2[30], ed3[30], ed4[30], ed5[30], ed6[50], ed7[50]; + char ed1[50], ed2[50], ed3[50], ed4[50], ed5[50], ed6[50], ed7[50], ed8[50]; struct tm tm; db_lock(mdb); @@ -385,8 +395,8 @@ db_create_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) "INSERT INTO Media (VolumeName,MediaType,PoolId,MaxVolBytes,VolCapacityBytes," "Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles," "VolStatus,Slot,VolBytes,InChanger,VolReadTime,VolWriteTime,VolParts," -"EndFile,EndBlock,LabelType) " -"VALUES ('%s','%s',%u,%s,%s,%d,%s,%s,%u,%u,'%s',%d,%s,%d,%s,%s,%d,0,0,%d)", +"EndFile,EndBlock,LabelType,StorageId) " +"VALUES ('%s','%s',%u,%s,%s,%d,%s,%s,%u,%u,'%s',%d,%s,%d,%s,%s,%d,0,0,%d,%s)", mr->VolumeName, mr->MediaType, mr->PoolId, edit_uint64(mr->MaxVolBytes,ed1), @@ -403,7 +413,8 @@ db_create_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) edit_uint64(mr->VolReadTime, ed6), edit_uint64(mr->VolWriteTime, ed7), mr->VolParts, - mr->LabelType + mr->LabelType, + edit_int64(mr->StorageId, ed8) ); @@ -438,8 +449,6 @@ db_create_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) return stat; } - - /* * Create a Unique record for the client -- no duplicates * Returns: 0 on failure @@ -505,6 +514,9 @@ int db_create_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cr) } + + + /* * Create a Unique record for the counter -- no duplicates * Returns: 0 on failure diff --git a/bacula/src/cats/sql_get.c b/bacula/src/cats/sql_get.c index 968ebd865d..c7fbea4b8b 100644 --- a/bacula/src/cats/sql_get.c +++ b/bacula/src/cats/sql_get.c @@ -835,7 +835,7 @@ int db_get_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes," "MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs," "MaxVolFiles,Recycle,Slot,FirstWritten,LastWritten,InChanger," - "EndFile,EndBlock,VolParts,LabelType,LabelDate " + "EndFile,EndBlock,VolParts,LabelType,LabelDate,StorageId " "FROM Media WHERE MediaId=%s", edit_int64(mr->MediaId, ed1)); } else { /* find by name */ @@ -843,7 +843,7 @@ int db_get_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) "VolBytes,VolMounts,VolErrors,VolWrites,MaxVolBytes,VolCapacityBytes," "MediaType,VolStatus,PoolId,VolRetention,VolUseDuration,MaxVolJobs," "MaxVolFiles,Recycle,Slot,FirstWritten,LastWritten,InChanger," - "EndFile,EndBlock,VolParts,LabelType,LabelDate " + "EndFile,EndBlock,VolParts,LabelType,LabelDate,StorageId " "FROM Media WHERE VolumeName='%s'", mr->VolumeName); } @@ -891,6 +891,7 @@ int db_get_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) mr->LabelType = str_to_int64(row[26]); bstrncpy(mr->cLabelDate, row[27]!=NULL?row[27]:"", sizeof(mr->cLabelDate)); mr->LabelDate = (time_t)str_to_utime(mr->cLabelDate); + mr->StorageId = str_to_int64(row[28]); stat = mr->MediaId; } } else { diff --git a/bacula/src/cats/sql_list.c b/bacula/src/cats/sql_list.c index 7a1d177311..c97c5a4ad6 100644 --- a/bacula/src/cats/sql_list.c +++ b/bacula/src/cats/sql_list.c @@ -142,7 +142,7 @@ db_list_media_records(JCR *jcr, B_DB *mdb, MEDIA_DBR *mdbr, "VolFiles,VolBlocks,VolMounts,VolBytes,VolErrors,VolWrites," "VolCapacityBytes,VolStatus,Recycle,VolRetention," "VolUseDuration,MaxVolJobs,MaxVolFiles,MaxVolBytes,InChanger," - "EndFile,EndBlock,VolParts,LabelType" + "EndFile,EndBlock,VolParts,LabelType,StorageId" " FROM Media WHERE Media.VolumeName='%s'", mdbr->VolumeName); } else { Mmsg(mdb->cmd, "SELECT MediaId,VolumeName,Slot,PoolId," @@ -150,7 +150,7 @@ db_list_media_records(JCR *jcr, B_DB *mdb, MEDIA_DBR *mdbr, "VolFiles,VolBlocks,VolMounts,VolBytes,VolErrors,VolWrites," "VolCapacityBytes,VolStatus,Recycle,VolRetention," "VolUseDuration,MaxVolJobs,MaxVolFiles,MaxVolBytes,InChanger," - "EndFile,EndBlock,VolParts,LabelType" + "EndFile,EndBlock,VolParts,LabelType,StorageId" " FROM Media WHERE Media.PoolId=%s ORDER BY MediaId", edit_int64(mdbr->PoolId, ed1)); } diff --git a/bacula/src/cats/sql_update.c b/bacula/src/cats/sql_update.c index f02578ff05..e3f0779239 100644 --- a/bacula/src/cats/sql_update.c +++ b/bacula/src/cats/sql_update.c @@ -258,6 +258,22 @@ db_update_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr) return stat; } +bool +db_update_storage_record(JCR *jcr, B_DB *mdb, STORAGE_DBR *sr) +{ + int stat; + char ed1[50]; + + db_lock(mdb); + Mmsg(mdb->cmd, "UPDATE Storage SET AutoChanger=%d WHERE StorageId=%s", + sr->AutoChanger, edit_int64(sr->StorageId, ed1)); + + stat = UPDATE_DB(jcr, mdb, mdb->cmd); + db_unlock(mdb); + return stat; +} + + /* * Update the Media Record at end of Session * @@ -271,7 +287,7 @@ db_update_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) time_t ttime; struct tm tm; int stat; - char ed1[30], ed2[30], ed3[30], ed4[30]; + char ed1[50], ed2[50], ed3[50], ed4[50], ed5[50]; Dmsg1(100, "update_media: FirstWritten=%d\n", mr->FirstWritten); @@ -297,47 +313,35 @@ db_update_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) strftime(dt, sizeof(dt), "%Y-%m-%d %T", &tm); Mmsg(mdb->cmd, "UPDATE Media SET LabelDate='%s' " "WHERE VolumeName='%s'", dt, mr->VolumeName); - stat = UPDATE_DB(jcr, mdb, mdb->cmd); + UPDATE_DB(jcr, mdb, mdb->cmd); } if (mr->LastWritten != 0) { ttime = mr->LastWritten; localtime_r(&ttime, &tm); strftime(dt, sizeof(dt), "%Y-%m-%d %T", &tm); - - Mmsg(mdb->cmd, "UPDATE Media SET VolJobs=%u," - "VolFiles=%u,VolBlocks=%u,VolBytes=%s,VolMounts=%u,VolErrors=%u," - "VolWrites=%u,MaxVolBytes=%s,LastWritten='%s',VolStatus='%s'," - "Slot=%d,InChanger=%d,VolReadTime=%s,VolWriteTime=%s,VolParts=%d," - "LabelType=%d" - " WHERE VolumeName='%s'", - mr->VolJobs, mr->VolFiles, mr->VolBlocks, edit_uint64(mr->VolBytes, ed1), - mr->VolMounts, mr->VolErrors, mr->VolWrites, - edit_uint64(mr->MaxVolBytes, ed2), dt, - mr->VolStatus, mr->Slot, mr->InChanger, - edit_uint64(mr->VolReadTime, ed3), - edit_uint64(mr->VolWriteTime, ed4), - mr->VolParts, - mr->LabelType, - mr->VolumeName); - } else { - Mmsg(mdb->cmd, "UPDATE Media SET VolJobs=%u," - "VolFiles=%u,VolBlocks=%u,VolBytes=%s,VolMounts=%u,VolErrors=%u," - "VolWrites=%u,MaxVolBytes=%s,VolStatus='%s'," - "Slot=%d,InChanger=%d,VolReadTime=%s,VolWriteTime=%s,VolParts=%d," - "LabelType=%d" - " WHERE VolumeName='%s'", - mr->VolJobs, mr->VolFiles, mr->VolBlocks, edit_uint64(mr->VolBytes, ed1), - mr->VolMounts, mr->VolErrors, mr->VolWrites, - edit_uint64(mr->MaxVolBytes, ed2), - mr->VolStatus, mr->Slot, mr->InChanger, - edit_uint64(mr->VolReadTime, ed3), - edit_uint64(mr->VolWriteTime, ed4), - mr->VolParts, - mr->LabelType, - mr->VolumeName); + Mmsg(mdb->cmd, "UPDATE Media Set LastWritten='%s' " + "WHERE VolumeName='%s'", dt, mr->VolumeName); + UPDATE_DB(jcr, mdb, mdb->cmd); } + Mmsg(mdb->cmd, "UPDATE Media SET VolJobs=%u," + "VolFiles=%u,VolBlocks=%u,VolBytes=%s,VolMounts=%u,VolErrors=%u," + "VolWrites=%u,MaxVolBytes=%s,VolStatus='%s'," + "Slot=%d,InChanger=%d,VolReadTime=%s,VolWriteTime=%s,VolParts=%d," + "LabelType=%d,StorageId=%s" + " WHERE VolumeName='%s'", + mr->VolJobs, mr->VolFiles, mr->VolBlocks, edit_uint64(mr->VolBytes, ed1), + mr->VolMounts, mr->VolErrors, mr->VolWrites, + edit_uint64(mr->MaxVolBytes, ed2), + mr->VolStatus, mr->Slot, mr->InChanger, + edit_uint64(mr->VolReadTime, ed3), + edit_uint64(mr->VolWriteTime, ed4), + mr->VolParts, + mr->LabelType, + edit_int64(mr->StorageId, ed5), + mr->VolumeName); + Dmsg1(400, "%s\n", mdb->cmd); stat = UPDATE_DB(jcr, mdb, mdb->cmd); @@ -406,9 +410,9 @@ db_make_inchanger_unique(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr) char ed1[50], ed2[50]; if (mr->InChanger != 0 && mr->Slot != 0) { Mmsg(mdb->cmd, "UPDATE Media SET InChanger=0 WHERE " - "Slot=%d AND PoolId=%s AND MediaId!=%s", + "Slot=%d AND StorageId=%s AND MediaId!=%s", mr->Slot, - edit_int64(mr->PoolId, ed1), edit_int64(mr->MediaId, ed2)); + edit_int64(mr->StorageId, ed1), edit_int64(mr->MediaId, ed2)); Dmsg1(400, "%s\n", mdb->cmd); UPDATE_DB(jcr, mdb, mdb->cmd); } diff --git a/bacula/src/dird/catreq.c b/bacula/src/dird/catreq.c index a1eb4fc926..fd53c276c8 100644 --- a/bacula/src/dird/catreq.c +++ b/bacula/src/dird/catreq.c @@ -250,9 +250,7 @@ void catalog_request(JCR *jcr, BSOCK *bs, char *msg) * Check if it has expired, and if not update the DB. Note, if * Volume has expired, has_volume_expired() will update the DB. */ - if (has_volume_expired(jcr, &mr)) { - send_volume_info_to_storage_daemon(jcr, bs, &mr); - } else if (db_update_media_record(jcr, jcr->db, &mr)) { + if (has_volume_expired(jcr, &mr) || db_update_media_record(jcr, jcr->db, &mr)) { send_volume_info_to_storage_daemon(jcr, bs, &mr); } else { Jmsg(jcr, M_FATAL, 0, _("Catalog error updating Media record. %s"), diff --git a/bacula/src/dird/dird.c b/bacula/src/dird/dird.c index 7a419f49e9..431583aa2d 100644 --- a/bacula/src/dird/dird.c +++ b/bacula/src/dird/dird.c @@ -641,7 +641,6 @@ static int check_resources() create_pool(NULL, db, pool, POOL_OP_UPDATE); /* update request */ } - /* ***FIXME*** we need to update store and media_type records */ STORE *store; foreach_res(store, R_STORAGE) { STORAGE_DBR sr; @@ -653,10 +652,13 @@ static int check_resources() } else { mr.MediaTypeId = 0; } - sr.MediaTypeId = mr.MediaTypeId; bstrncpy(sr.Name, store->name(), sizeof(sr.Name)); sr.AutoChanger = store->autochanger; db_create_storage_record(NULL, db, &sr); + store->StorageId = sr.StorageId; /* set storage Id */ + if (!sr.created) { /* if not created, update it */ + db_update_storage_record(NULL, db, &sr); + } } /* Loop over all counters, defining them in each database */ diff --git a/bacula/src/dird/dird.h b/bacula/src/dird/dird.h index 37136a123a..fe00fffb0c 100644 --- a/bacula/src/dird/dird.h +++ b/bacula/src/dird/dird.h @@ -6,7 +6,7 @@ * Version $Id$ */ /* - Copyright (C) 2000-2004 Kern Sibbald and John Walker + Copyright (C) 2000-2005 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as diff --git a/bacula/src/dird/dird_conf.c b/bacula/src/dird/dird_conf.c index 5b812ead8e..99d9006c4c 100644 --- a/bacula/src/dird/dird_conf.c +++ b/bacula/src/dird/dird_conf.c @@ -221,6 +221,9 @@ RES_ITEM job_items[] = { {"writebootstrap",store_dir, ITEM(res_job.WriteBootstrap), 0, 0, 0}, {"replace", store_replace, ITEM(res_job.replace), 0, ITEM_DEFAULT, REPLACE_ALWAYS}, {"maxruntime", store_time, ITEM(res_job.MaxRunTime), 0, 0, 0}, + {"fullmaxwaittime", store_time, ITEM(res_job.FullMaxWaitTime), 0, 0, 0}, + {"incrementalmaxwaittime", store_time, ITEM(res_job.IncMaxWaitTime), 0, 0, 0}, + {"differentialmaxwaittime", store_time, ITEM(res_job.DiffMaxWaitTime), 0, 0, 0}, {"maxwaittime", store_time, ITEM(res_job.MaxWaitTime), 0, 0, 0}, {"maxstartdelay",store_time, ITEM(res_job.MaxStartDelay), 0, 0, 0}, {"jobretention", store_time, ITEM(res_job.JobRetention), 0, 0, 0}, @@ -477,11 +480,12 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm break; case R_STORAGE: sendit(sock, "Storage: name=%s address=%s SDport=%d MaxJobs=%u\n" -" DeviceName=%s MediaType=%s\n", +" DeviceName=%s MediaType=%s StorageId=%s\n", res->res_store.hdr.name, res->res_store.address, res->res_store.SDport, res->res_store.MaxConcurrentJobs, res->res_store.dev_name(), - res->res_store.media_type); + res->res_store.media_type, + edit_int64(res->res_store.StorageId, ed1)); break; case R_CATALOG: sendit(sock, "Catalog: name=%s address=%s DBport=%d db_name=%s\n" diff --git a/bacula/src/dird/dird_conf.h b/bacula/src/dird/dird_conf.h index b1542aa1b3..745dd554e2 100644 --- a/bacula/src/dird/dird_conf.h +++ b/bacula/src/dird/dird_conf.h @@ -220,6 +220,8 @@ public: uint32_t NumConcurrentJobs; /* number of concurrent jobs running */ int enable_ssl; /* Use SSL */ + int64_t StorageId; /* Set from Storage DB record */ + char *dev_name() const; char *name() const; }; @@ -255,6 +257,9 @@ public: int replace; /* How (overwrite, ..) */ utime_t MaxRunTime; /* max run time in seconds */ utime_t MaxWaitTime; /* max blocking time in seconds */ + utime_t FullMaxWaitTime; /* Max Full job wait time */ + utime_t DiffMaxWaitTime; /* Max Differential job wait time */ + utime_t IncMaxWaitTime; /* Max Incremental job wait time */ utime_t MaxStartDelay; /* max start delay in seconds */ int PrefixLinks; /* prefix soft links with Where path */ int PruneJobs; /* Force pruning of Jobs */ diff --git a/bacula/src/dird/job.c b/bacula/src/dird/job.c index 1107ef425b..da1d5d29ae 100644 --- a/bacula/src/dird/job.c +++ b/bacula/src/dird/job.c @@ -436,18 +436,32 @@ static void job_monitor_watchdog(watchdog_t *self) static bool job_check_maxwaittime(JCR *control_jcr, JCR *jcr) { bool cancel = false; + bool ok_to_cancel = false; + JOB *job = jcr->job; - if (jcr->job->MaxWaitTime == 0) { + if (job->MaxWaitTime == 0 && job->FullMaxWaitTime == 0 && + job->IncMaxWaitTime == 0 && job->DiffMaxWaitTime == 0) { return false; - } - if ((watchdog_time - jcr->start_time) < jcr->job->MaxWaitTime) { - Dmsg3(800, "Job %p (%s) with MaxWaitTime %d not expired\n", - jcr, jcr->Job, jcr->job->MaxWaitTime); + } + if (jcr->JobLevel == L_FULL && job->FullMaxWaitTime != 0 && + (watchdog_time - jcr->start_time) >= job->FullMaxWaitTime) { + ok_to_cancel = true; + } else if (jcr->JobLevel == L_DIFFERENTIAL && job->DiffMaxWaitTime != 0 && + (watchdog_time - jcr->start_time) >= job->DiffMaxWaitTime) { + ok_to_cancel = true; + } else if (jcr->JobLevel == L_INCREMENTAL && job->IncMaxWaitTime != 0 && + (watchdog_time - jcr->start_time) >= job->IncMaxWaitTime) { + ok_to_cancel = true; + } else if (job->MaxWaitTime != 0 && + (watchdog_time - jcr->start_time) >= job->MaxWaitTime) { + ok_to_cancel = true; + } + if (!ok_to_cancel) { return false; } Dmsg3(800, "Job %d (%s): MaxWaitTime of %d seconds exceeded, " "checking status\n", - jcr->JobId, jcr->Job, jcr->job->MaxWaitTime); + jcr->JobId, jcr->Job, job->MaxWaitTime); switch (jcr->JobStatus) { case JS_Created: case JS_Blocked: diff --git a/bacula/src/dird/next_vol.c b/bacula/src/dird/next_vol.c index 34b84b9133..bf44fc8442 100644 --- a/bacula/src/dird/next_vol.c +++ b/bacula/src/dird/next_vol.c @@ -9,7 +9,7 @@ * Version $Id$ */ /* - Copyright (C) 2001-2004 Kern Sibbald and John Walker + Copyright (C) 2001-2005 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -71,7 +71,7 @@ int find_next_volume_for_append(JCR *jcr, MEDIA_DBR *mr, bool create) * 2. Try finding a recycled volume */ ok = find_recycled_volume(jcr, InChanger, mr); - Dmsg2(100, "find_recycled_volume %d FW=%d\n", ok, mr->FirstWritten); + Dmsg2(100, "find_recycled_volume %d FW=%d\n", ok, mr->FirstWritten); if (!ok) { /* * 3. Try recycling any purged volume @@ -89,10 +89,10 @@ int find_next_volume_for_append(JCR *jcr, MEDIA_DBR *mr, bool create) continue; /* retry again accepting any volume */ } } - Dmsg2(200, "find_recycled_volume2 %d FW=%d\n", ok, mr->FirstWritten); + Dmsg2(200, "find_recycled_volume2 %d FW=%d\n", ok, mr->FirstWritten); if (!ok && create) { /* - * 5. Try "creating" a new Volume + * 5. Try "creating" a new Volume */ ok = newVolume(jcr, mr); } @@ -104,32 +104,32 @@ int find_next_volume_for_append(JCR *jcr, MEDIA_DBR *mr, bool create) */ if (!ok && (jcr->pool->purge_oldest_volume || jcr->pool->recycle_oldest_volume)) { - Dmsg2(200, "No next volume found. PurgeOldest=%d\n RecyleOldest=%d", + 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, InChanger, mr); - Dmsg1(400, "Find oldest=%d\n", ok); + Dmsg1(400, "Find oldest=%d\n", ok); if (ok) { UAContext *ua; - Dmsg0(400, "Try purge.\n"); + Dmsg0(400, "Try purge.\n"); /* * 5. Try to purging oldest volume only if not UA calling us. */ ua = new_ua_context(jcr); if (jcr->pool->purge_oldest_volume && create) { - Jmsg(jcr, M_INFO, 0, _("Purging oldest volume \"%s\"\n"), mr->VolumeName); + Jmsg(jcr, M_INFO, 0, _("Purging oldest volume \"%s\"\n"), mr->VolumeName); ok = purge_jobs_from_volume(ua, mr); /* * 5. or try recycling the oldest volume */ } else if (jcr->pool->recycle_oldest_volume) { - Jmsg(jcr, M_INFO, 0, _("Pruning oldest volume \"%s\"\n"), mr->VolumeName); + Jmsg(jcr, M_INFO, 0, _("Pruning oldest volume \"%s\"\n"), mr->VolumeName); ok = prune_volume(ua, mr); } free_ua_context(ua); if (ok) { ok = recycle_volume(jcr, mr); - Dmsg1(400, "Recycle after purge oldest=%d\n", ok); + Dmsg1(400, "Recycle after purge oldest=%d\n", ok); } } } @@ -167,30 +167,30 @@ bool has_volume_expired(JCR *jcr, MEDIA_DBR *mr) if (strcmp(mr->VolStatus, "Append") == 0 && mr->VolJobs > 0) { /* First handle Max Volume Bytes */ if ((mr->MaxVolBytes > 0 && mr->VolBytes >= mr->MaxVolBytes)) { - Jmsg(jcr, M_INFO, 0, _("Max Volume bytes exceeded. " - "Marking Volume \"%s\" as Full.\n"), mr->VolumeName); - bstrncpy(mr->VolStatus, "Full", sizeof(mr->VolStatus)); + Jmsg(jcr, M_INFO, 0, _("Max Volume bytes exceeded. " + "Marking Volume \"%s\" as Full.\n"), mr->VolumeName); + bstrncpy(mr->VolStatus, "Full", sizeof(mr->VolStatus)); expired = true; /* Now see if Volume should only be used once */ } else if (mr->VolBytes > 0 && jcr->pool->use_volume_once) { - Jmsg(jcr, M_INFO, 0, _("Volume used once. " - "Marking Volume \"%s\" as Used.\n"), mr->VolumeName); - bstrncpy(mr->VolStatus, "Used", sizeof(mr->VolStatus)); + Jmsg(jcr, M_INFO, 0, _("Volume used once. " + "Marking Volume \"%s\" as Used.\n"), mr->VolumeName); + bstrncpy(mr->VolStatus, "Used", sizeof(mr->VolStatus)); expired = true; /* Now see if Max Jobs written to volume */ } else if (mr->MaxVolJobs > 0 && mr->MaxVolJobs <= mr->VolJobs) { - Jmsg(jcr, M_INFO, 0, _("Max Volume jobs exceeded. " - "Marking Volume \"%s\" as Used.\n"), mr->VolumeName); - bstrncpy(mr->VolStatus, "Used", sizeof(mr->VolStatus)); + Jmsg(jcr, M_INFO, 0, _("Max Volume jobs exceeded. " + "Marking Volume \"%s\" as Used.\n"), mr->VolumeName); + bstrncpy(mr->VolStatus, "Used", sizeof(mr->VolStatus)); expired = true; /* Now see if Max Files written to volume */ } else if (mr->MaxVolFiles > 0 && mr->MaxVolFiles <= mr->VolFiles) { - Jmsg(jcr, M_INFO, 0, _("Max Volume files exceeded. " - "Marking Volume \"%s\" as Used.\n"), mr->VolumeName); - bstrncpy(mr->VolStatus, "Used", sizeof(mr->VolStatus)); + Jmsg(jcr, M_INFO, 0, _("Max Volume files exceeded. " + "Marking Volume \"%s\" as Used.\n"), mr->VolumeName); + bstrncpy(mr->VolStatus, "Used", sizeof(mr->VolStatus)); expired = true; /* Finally, check Use duration expiration */ @@ -198,9 +198,9 @@ bool has_volume_expired(JCR *jcr, MEDIA_DBR *mr) utime_t now = time(NULL); /* See if Vol Use has expired */ if (mr->VolUseDuration <= (now - mr->FirstWritten)) { - Jmsg(jcr, M_INFO, 0, _("Max configured use duration exceeded. " - "Marking Volume \"%s\" as Used.\n"), mr->VolumeName); - bstrncpy(mr->VolStatus, "Used", sizeof(mr->VolStatus)); + Jmsg(jcr, M_INFO, 0, _("Max configured use duration exceeded. " + "Marking Volume \"%s\" as Used.\n"), mr->VolumeName); + bstrncpy(mr->VolStatus, "Used", sizeof(mr->VolStatus)); expired = true; } } @@ -208,7 +208,7 @@ bool has_volume_expired(JCR *jcr, MEDIA_DBR *mr) if (expired) { /* Need to update media */ if (!db_update_media_record(jcr, jcr->db, mr)) { - Jmsg(jcr, M_ERROR, 0, _("Catalog error updating volume \"%s\". ERR=%s"), + Jmsg(jcr, M_ERROR, 0, _("Catalog error updating volume \"%s\". ERR=%s"), mr->VolumeName, db_strerror(jcr->db)); } } @@ -247,12 +247,12 @@ void check_if_volume_valid_or_recyclable(JCR *jcr, MEDIA_DBR *mr, const char **r */ if (strcmp(mr->VolStatus, "Purged") == 0) { if (recycle_volume(jcr, mr)) { - Jmsg(jcr, M_INFO, 0, "Recycled current volume \"%s\"\n", mr->VolumeName); + Jmsg(jcr, M_INFO, 0, "Recycled current volume \"%s\"\n", mr->VolumeName); *reason = NULL; return; } else { - /* In principle this shouldn't happen */ - *reason = "and recycling of current volume failed"; + /* In principle this shouldn't happen */ + *reason = "and recycling of current volume failed"; return; } } @@ -268,8 +268,8 @@ void check_if_volume_valid_or_recyclable(JCR *jcr, MEDIA_DBR *mr, const char **r */ if ((mr->LastWritten + mr->VolRetention) < (utime_t)time(NULL) && mr->Recycle && jcr->pool->recycle_current_volume - && (strcmp(mr->VolStatus, "Full") == 0 || - strcmp(mr->VolStatus, "Used") == 0)) { + && (strcmp(mr->VolStatus, "Full") == 0 || + strcmp(mr->VolStatus, "Used") == 0)) { /* * Attempt prune of current volume to see if we can * recycle it for use. @@ -283,15 +283,15 @@ void check_if_volume_valid_or_recyclable(JCR *jcr, MEDIA_DBR *mr, const char **r if (ok) { /* If fully purged, recycle current volume */ if (recycle_volume(jcr, mr)) { - Jmsg(jcr, M_INFO, 0, "Recycled current volume \"%s\"\n", mr->VolumeName); + Jmsg(jcr, M_INFO, 0, "Recycled current volume \"%s\"\n", mr->VolumeName); *reason = NULL; } else { - *reason = "but should be Append, Purged or Recycle (recycling of the " - "current volume failed)"; + *reason = "but should be Append, Purged or Recycle (recycling of the " + "current volume failed)"; } } else { - *reason = "but should be Append, Purged or Recycle (cannot automatically " - "recycle current volume, as it still contains unpruned data)"; + *reason = "but should be Append, Purged or Recycle (cannot automatically " + "recycle current volume, as it still contains unpruned data)"; } } } diff --git a/bacula/src/dird/recycle.c b/bacula/src/dird/recycle.c index a4e15bb906..c242d1bc81 100644 --- a/bacula/src/dird/recycle.c +++ b/bacula/src/dird/recycle.c @@ -9,7 +9,7 @@ */ /* - Copyright (C) 2002-2004 Kern Sibbald and John Walker + Copyright (C) 2002-20054 Kern Sibbald This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as diff --git a/bacula/src/dird/ua_cmds.c b/bacula/src/dird/ua_cmds.c index 273d1500e8..8146d281d4 100644 --- a/bacula/src/dird/ua_cmds.c +++ b/bacula/src/dird/ua_cmds.c @@ -862,7 +862,6 @@ static void update_vol_pool(UAContext *ua, char *val, MEDIA_DBR *mr, POOL_DBR *o if (!db_update_pool_record(ua->jcr, ua->db, &pr)) { bsendmsg(ua, "%s", db_strerror(ua->db)); } - db_make_inchanger_unique(ua->jcr, ua->db, mr); } db_unlock(ua->db); free_pool_memory(query); diff --git a/bacula/src/dird/ua_label.c b/bacula/src/dird/ua_label.c index 423678c933..eecd1ee946 100644 --- a/bacula/src/dird/ua_label.c +++ b/bacula/src/dird/ua_label.c @@ -213,6 +213,7 @@ int update_slots(UAContext *ua) memset(&mr, 0, sizeof(mr)); mr.Slot = vl->Slot; mr.InChanger = 1; + mr.StorageId = store->StorageId; /* Set InChanger to zero for this Slot */ db_lock(ua->db); db_make_inchanger_unique(ua->jcr, ua->db, &mr); @@ -224,30 +225,32 @@ int update_slots(UAContext *ua) bstrncpy(mr.VolumeName, vl->VolName, sizeof(mr.VolumeName)); db_lock(ua->db); if (db_get_media_record(ua->jcr, ua->db, &mr)) { - if (mr.Slot != vl->Slot || !mr.InChanger) { - mr.Slot = vl->Slot; - mr.InChanger = 1; - if (!db_update_media_record(ua->jcr, ua->db, &mr)) { - bsendmsg(ua, "%s", db_strerror(ua->db)); - } else { - bsendmsg(ua, _( - "Catalog record for Volume \"%s\" updated to reference slot %d.\n"), - mr.VolumeName, mr.Slot); - } - } else { - bsendmsg(ua, _("Catalog record for Volume \"%s\" is up to date.\n"), - mr.VolumeName); - } - db_unlock(ua->db); - continue; + if (mr.Slot != vl->Slot || !mr.InChanger || mr.StorageId != store->StorageId) { + mr.Slot = vl->Slot; + mr.InChanger = 1; + mr.StorageId = store->StorageId; + if (!db_update_media_record(ua->jcr, ua->db, &mr)) { + bsendmsg(ua, "%s", db_strerror(ua->db)); + } else { + bsendmsg(ua, _( + "Catalog record for Volume \"%s\" updated to reference slot %d.\n"), + mr.VolumeName, mr.Slot); + } + } else { + bsendmsg(ua, _("Catalog record for Volume \"%s\" is up to date.\n"), + mr.VolumeName); + } + db_unlock(ua->db); + continue; } else { - bsendmsg(ua, _("Record for Volume \"%s\" not found in catalog.\n"), + bsendmsg(ua, _("Record for Volume \"%s\" not found in catalog.\n"), mr.VolumeName); } db_unlock(ua->db); } memset(&mr, 0, sizeof(mr)); mr.InChanger = 1; + mr.StorageId = store->StorageId; db_lock(ua->db); for (int i=1; iSlot, mr.VolumeName); - if (!mr.InChanger) { - mr.InChanger = 1; - if (!db_update_media_record(ua->jcr, ua->db, &mr)) { - bsendmsg(ua, "Error setting InChanger: ERR=%s", db_strerror(ua->db)); - } + mr.Slot = vl->Slot; + mr.InChanger = 1; + mr.StorageId = store->StorageId; + if (!db_update_media_record(ua->jcr, ua->db, &mr)) { + bsendmsg(ua, "Error setting InChanger: ERR=%s", db_strerror(ua->db)); } continue; } diff --git a/bacula/src/stored/stored_conf.c b/bacula/src/stored/stored_conf.c index dd2fa42415..4589a1daa7 100644 --- a/bacula/src/stored/stored_conf.c +++ b/bacula/src/stored/stored_conf.c @@ -443,6 +443,8 @@ void save_resource(int type, RES_ITEM *items, int pass) * record. */ if (pass == 2) { + DEVRES *dev; + int errstat; switch (type) { /* Resources not containing a resource */ case R_DIRECTOR: @@ -464,6 +466,14 @@ void save_resource(int type, RES_ITEM *items, int pass) } /* we must explicitly copy the device alist pointer */ res->res_changer.device = res_all.res_changer.device; + foreach_alist(dev, res->res_changer.device) { + dev->changer_res = (AUTOCHANGER *)&res->res_changer; + } + if ((errstat = pthread_mutex_init(&dev->changer_res->changer_mutex, NULL)) != 0) { + berrno be; + Jmsg1(NULL, M_ERROR_TERM, 0, _("Unable to init mutex: ERR=%s\n"), + be.strerror(errstat)); + } break; default: printf("Unknown resource type %d\n", type); diff --git a/bacula/src/stored/stored_conf.h b/bacula/src/stored/stored_conf.h index 448f41a879..44a9331a12 100644 --- a/bacula/src/stored/stored_conf.h +++ b/bacula/src/stored/stored_conf.h @@ -71,6 +71,15 @@ public: }; typedef struct s_res_store STORES; +class AUTOCHANGER { +public: + RES hdr; + alist *device; + char *changer_name; /* Changer device name */ + char *changer_command; /* Changer command -- external program */ + pthread_mutex_t changer_mutex; /* One changer operation at a time */ +}; + /* Device specific definitions */ class DEVRES { public: @@ -108,16 +117,11 @@ public: char *write_part_command; /* Write part command */ char *free_space_command; /* Free space command */ + /* The following are set at runtime */ DEVICE *dev; /* Pointer to phyical dev -- set at runtime */ + AUTOCHANGER *changer_res; /* pointer to changer res if any */ }; -class AUTOCHANGER { -public: - RES hdr; - alist *device; - char *changer_name; /* Changer device name */ - char *changer_command; /* Changer command -- external program */ -}; union URES { DIRRES res_dir; diff --git a/bacula/src/version.h b/bacula/src/version.h index 698129b2c1..7246bc8f76 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -1,8 +1,8 @@ /* */ #undef VERSION #define VERSION "1.37.4" -#define BDATE "18 February 2005" -#define LSMDATE "18Feb05" +#define BDATE "20 February 2005" +#define LSMDATE "20Feb05" /* Debug flags */ #undef DEBUG -- 2.39.5