- Figure out how to use ssh or stunnel to protect Bacula communications.
For 1.33 Testing/Documentation:
+- Document new alias records in Director. SDAddress SDDeviceName, SDPassword.
+ FDPassword, FDAddress, DBAddress, DBPort, DBPassword.
+- Document new Include/Exclude ...
+- Add test of exclusion, test multiple Include {} statements.
+- Add counter variable test.
+- Document ln -sf /usr/lib/libncurses.so /usr/lib/libtermcap.so
+ and install the esound-dev package for compiling Console on SuSE.
+- Add an example of using a FIFO in dirdconf.wml
+- Add an item to the FAQ about running jobs in different timezones.
+- Add some examples of job editing codes.
+- Add Dan's 31 Oct 2003 email on tcpwrappers to Tips.
+- Add to supported autochangers
+ OS : FreeBSD-4.9
+ Auto-Changer : QUALSTAR TLS-4210
+ Manufufactur : Qualstar
+ Tapes : 12 (AIT1: 36GB, AIT2: 50GB all uncompressed)
+ Drives : 2xAIT2 (installed in the Qualstar: SONY SDX-500C AIT2)
+- Setup a standard job that builds a bootstrap file and saves
+ it with the catalog database.
+- Document Dan's new --with-dir-user, ... options.
+
+
+For 1.33
+- Add a default DB password to MySQL.
+ GRANT all privileges ON bacula.* TO bacula@localhost IDENTIFIED BY
+ 'bacula_password';
+ FLUSH PRIVILEGES;
- Define week of year for scheduler. W01, W02, ...
Week 01 of a year is per definition the first week that has the
Thursday in this year, which is equivalent to the week that contains the
it to tape.
- Scratch Pool where the volumes can be re-assigned to any Pool.
- bextract is sending everything to the log file ****FIXME****
-- Document new alias records in Director. SDAddress SDDeviceName, SDPassword.
- FDPassword, FDAddress, DBAddress, DBPort, DBPassword.
-- Document new Include/Exclude ...
-- Add test of exclusion, test multiple Include {} statements.
-- Add counter variable test.
-- Document ln -sf /usr/lib/libncurses.so /usr/lib/libtermcap.so
- and install the esound-dev package for compiling Console on SuSE.
-- Add an example of using a FIFO in dirdconf.wml
-- Add an item to the FAQ about running jobs in different timezones.
-- Add some examples of job editing codes.
-- Add Dan's 31 Oct 2003 email on tcpwrappers to Tips.
-- Add to supported autochangers
- OS : FreeBSD-4.9
- Auto-Changer : QUALSTAR TLS-4210
- Manufufactur : Qualstar
- Tapes : 12 (AIT1: 36GB, AIT2: 50GB all uncompressed)
- Drives : 2xAIT2 (installed in the Qualstar: SONY SDX-500C AIT2)
-- Setup a standard job that builds a bootstrap file and saves
- it with the catalog database.
-- Document Dan's new --with-dir-user, ... options.
-
-For 1.33
- Add Progress command that periodically reports the progress of
a job or all jobs.
- Restrict characters permitted in a Resource name, and don't permit
/* sql.c */
B_DB *db_init_database(JCR *jcr, char *db_name, char *db_user, char *db_password,
- char *db_address, int db_port, char *db_socket);
+ char *db_address, int db_port, char *db_socket);
int db_open_database(JCR *jcr, B_DB *db);
void db_close_database(JCR *jcr, B_DB *db);
void db_escape_string(char *snew, char *old, int len);
int db_create_media_record(JCR *jcr, B_DB *db, MEDIA_DBR *media_dbr);
int db_create_client_record(JCR *jcr, B_DB *db, CLIENT_DBR *cr);
int db_create_fileset_record(JCR *jcr, B_DB *db, FILESET_DBR *fsr);
-int db_create_pool_record(JCR *jcr, B_DB *db, POOL_DBR *pool_dbr);
+int db_create_pool_record(JCR *jcr, B_DB *db, POOL_DBR *pool_dbr);
int db_create_jobmedia_record(JCR *jcr, B_DB *mdb, JOBMEDIA_DBR *jr);
int db_create_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr);
int db_update_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr);
int db_add_SIG_to_file_record(JCR *jcr, B_DB *mdb, FileId_t FileId, char *SIG, int type);
int db_mark_file_record(JCR *jcr, B_DB *mdb, FileId_t FileId, JobId_t JobId);
+void db_make_slot_unique(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr);
#endif /* __SQL_PROTOS_H */
/*
- * Create Unique Media record
+ * Create Media record. VolumeName and non-zero Slot must be unique
+ *
* Returns: 0 on failure
* 1 on success
*/
sql_free_result(mdb);
}
+ /* Make sur Slot, if non-zero, is unique */
+ db_make_slot_unique(jcr, mdb, mr);
+
/* Must create it */
if (mr->LabelDate) {
localtime_r(&mr->LabelDate, &tm);
}
localtime_r(&ttime, &tm);
strftime(dt, sizeof(dt), "%Y-%m-%d %T", &tm);
- Mmsg(&mdb->cmd, "UPDATE Media SET LabelDate='%s'\
- WHERE VolumeName='%s'", dt, mr->VolumeName);
+ Mmsg(&mdb->cmd, "UPDATE Media SET LabelDate='%s' "
+ "WHERE VolumeName='%s'", dt, mr->VolumeName);
stat = UPDATE_DB(jcr, mdb, mdb->cmd);
}
+
+ /* Make sure Slot, if non-zero, is unique */
+ db_make_slot_unique(jcr, mdb, mr);
ttime = mr->LastWritten;
localtime_r(&ttime, &tm);
return stat;
}
+/*
+ * If we have a non-zero Slot, ensure that no other Media
+ * record in this Pool has the same Slot by setting Slot=0.
+ *
+ * This routine assumes the database is already locked.
+ */
+void
+db_make_slot_unique(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
+{
+ if (mr->Slot != 0) {
+ Mmsg(&mdb->cmd, "UPDATE Media SET Slot=0 WHERE PoolId=%u "
+ "AND Slot=%d\n", mr->PoolId, mr->Slot);
+ Dmsg1(400, "%s\n", mdb->cmd);
+ UPDATE_DB(jcr, mdb, mdb->cmd);
+ }
+}
+
#endif /* HAVE_MYSQL || HAVE_SQLITE */
p = (char *)ie->name_list.get(j);
switch (*p) {
case '|':
+ p++; /* skip over the | */
fd->msg = edit_job_codes(jcr, fd->msg, p, "");
bpipe = open_bpipe(fd->msg, 0, "r");
if (!bpipe) {
*/
int find_next_volume_for_append(JCR *jcr, MEDIA_DBR *mr, int create)
{
- int ok, retry = 0;
+ int retry = 0;
+ bool ok;
mr->PoolId = jcr->PoolId;
bstrncpy(mr->MediaType, jcr->store->media_type, sizeof(mr->MediaType));
db_lock(jcr->db);
for ( ;; ) {
bstrncpy(mr->VolStatus, "Append", sizeof(mr->VolStatus)); /* want only appendable volumes */
+ /*
+ * 1. Look for volume with "Append" status.
+ */
ok = db_find_next_volume(jcr, jcr->db, 1, mr);
Dmsg2(100, "catreq after find_next_vol ok=%d FW=%d\n", ok, mr->FirstWritten);
if (!ok) {
- /* Well, try finding recycled volumes */
+ /*
+ * 2. Try finding a recycled volume
+ */
ok = find_recycled_volume(jcr, 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);
Dmsg2(200, "find_recycled_volume2 %d FW=%d\n", ok, mr->FirstWritten);
if (!ok && create) {
- /* See if we can create a new Volume */
+ /*
+ * 4. Try "creating" a new Volume
+ */
ok = newVolume(jcr, mr);
}
}
+ /*
+ * Look at more drastic ways to find an Appendable Volume
+ */
if (!ok && (jcr->pool->purge_oldest_volume ||
jcr->pool->recycle_oldest_volume)) {
Dmsg2(200, "No next volume found. PurgeOldest=%d\n RecyleOldest=%d",
if (ok) {
UAContext *ua;
Dmsg0(400, "Try purge.\n");
- /* Try to purge oldest volume */
+ /*
+ * 5. Try to purging oldest volume only if not UA calling us.
+ */
ua = new_ua_context(jcr);
- if (jcr->pool->purge_oldest_volume) {
+ if (jcr->pool->purge_oldest_volume && create) {
Jmsg(jcr, M_INFO, 0, _("Purging oldest volume \"%s\"\n"), mr->VolumeName);
ok = purge_jobs_from_volume(ua, mr);
- } else {
+ /*
+ * 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);
ok = prune_volume(ua, mr);
}
static void update_volpool(UAContext *ua, char *val, MEDIA_DBR *mr)
{
POOL_DBR pr;
- POOLMEM *query;
+
memset(&pr, 0, sizeof(pr));
bstrncpy(pr.Name, val, sizeof(pr.Name));
if (!get_pool_dbr(ua, &pr)) {
return;
}
- query = get_pool_memory(PM_MESSAGE);
- Mmsg(&query, "UPDATE Media SET PoolId=%u WHERE MediaId=%u", pr.PoolId, mr->MediaId);
- if (!db_sql_query(ua->db, query, NULL, NULL)) {
- bsendmsg(ua, "%s", db_strerror(ua->db));
- } else {
+ mr->PoolId = pr.PoolId; /* set new PoolId */
+ /*
+ * Make sure to use db_update... rather than doing this directly,
+ * so that any Slot is handled correctly.
+ */
+ if (!db_update_media_record(ua->jcr, ua->db, mr)) {
+ bsendmsg(ua, _("Error updating media record Pool: ERR=%s"), db_strerror(ua->db));
+ } else {
bsendmsg(ua, _("New Pool is: %s\n"), pr.Name);
}
- free_pool_memory(query);
}
/*
pr.MaxVols);
break;
}
- query = get_pool_memory(PM_MESSAGE);
- Mmsg(&query, "UPDATE Media SET Slot=%d WHERE MediaId=%u",
- slot, mr.MediaId);
- if (!db_sql_query(ua->db, query, NULL, NULL)) {
- bsendmsg(ua, "%s", db_strerror(ua->db));
+ mr.Slot = slot;
+ /*
+ * Make sure to use db_update... rather than doing this directly,
+ * so that any Slot is handled correctly.
+ */
+ if (!db_update_media_record(ua->jcr, ua->db, &mr)) {
+ bsendmsg(ua, _("Error updating media record Slot: ERR=%s"), db_strerror(ua->db));
} else {
- bsendmsg(ua, "New Slot is: %d\n", slot);
+ bsendmsg(ua, _("New Slot is: %s\n"), mr.Slot);
}
- free_pool_memory(query);
break;
case 8: /* Volume Files */
{
if (ua->db) {
db_close_database(ua->jcr, ua->db);
+ ua->db = NULL;
+ if (ua->jcr) {
+ ua->jcr->db = NULL;
+ }
}
- ua->db = NULL;
}
switch (*p) {
case '|':
+ p++; /* skip over | */
fn = get_pool_memory(PM_FNAME);
fn = edit_job_codes(jcr, fn, p, "");
bpipe = open_bpipe(fn, 0, "r");
{
#ifndef HAVE_CYGWIN
int i;
- int cpid;
+ pid_t cpid;
mode_t oldmask;
/*
* Become a daemon.
#undef VERSION
#define VERSION "1.33"
#define VSTRING "1"
-#define BDATE "06 Nov 2003"
-#define LSMDATE "06Nov03"
+#define BDATE "09 Nov 2003"
+#define LSMDATE "09Nov03"
/* Debug flags */
#undef DEBUG