From e0dd7ba56c76b55dca84a91e822a0673be30412a Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Mon, 7 Mar 2005 20:50:51 +0000 Subject: [PATCH] - Rework some of the autochanger data so that the DIR has the number of drives. - Modify the way the Device info is returned so that it comes back as a special message type and can be sent anytime the Device status changes. - Copy the change name and changer command into the device record if none is specified. - Require the change command and changer name to be specified in and AutoChanger resource. - Force all the Media Type records of all devices in an Autochanger to be the same. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@1873 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/kernstodo | 145 +++++++---------- bacula/src/dird/dird_conf.h | 3 +- bacula/src/dird/getmsg.c | 82 +++++++++- bacula/src/dird/msgchan.c | 43 +---- bacula/src/lib/jcr.c | 2 +- bacula/src/stored/askdir.c | 78 ++++++++++ bacula/src/stored/job.c | 60 ++----- bacula/src/stored/protos.h | 268 ++++++++++++++++---------------- bacula/src/stored/stored.c | 33 +++- bacula/src/stored/stored_conf.c | 208 ++++++++++++------------- bacula/src/stored/stored_conf.h | 96 ++++++------ bacula/src/version.h | 4 +- 12 files changed, 556 insertions(+), 466 deletions(-) diff --git a/bacula/kernstodo b/bacula/kernstodo index 34896383e5..1e772975d3 100644 --- a/bacula/kernstodo +++ b/bacula/kernstodo @@ -1,5 +1,5 @@ Kern's ToDo List - 22 February 2005 + 07 March 2005 Major development: Project Developer @@ -12,64 +12,42 @@ Version 1.37 Kern (see below) #3 Migration (Move, Copy, Archive Jobs) #4 Embedded Python Scripting (Implemented in Dir/SD) -#5 Events that call a Python program - (Implemented in Dir/SD) -#6 Select one from among Multiple Storage Devices for Job #7 Single Job Writing to Multiple Storage Devices ## Integrate web-bacula into a new Bacula project with bimagemgr. ## Consider moving docs to their own project. -Suggestions for Preben: -- Look at adding Client run command that will use the - port opened by the client. -- Optimized bootstrap. - Autochangers: -- Fix - Please use the "label" command to create a new Volume for: - Storage: DDS-4-changer - Media type: - Pool: Default - label - The defined Storage resources are: -- Copy Changer Device and Changer Command from Autochanger - to Device resource in SD if none given in Device resource. -- 3.Prevent two drives requesting the same Volume in any given +- 3. Prevent two drives requesting the same Volume in any given autochanger. -- 4. Use Changer Device and Changer Command specified in the - Autochanger resource, if none is found in the Device resource. - You can continue to specify them in the Device resource if you want - or need them to be different for each device. -- 5. Implement a new Device directive (perhaps "Autoselect = yes/no") - that can allow a Device be part of an Autochanger, and hence the changer - script protected, but if set to no, will prevent the Device from being - automatically selected from the changer. This allows the device to - be directly accessed through its Device name, but not through the - AutoChanger name. +- 3. Check if a Volume is mounted on another drive in an Autochanger. - 7. Implement new Console commands to allow offlining/reserving drives, and possibly manipulating the autochanger (much asked for). - 8. Automatic updating of Drive status from SD to DIR when something changes (Volume, offline, append, read, ...). -- 9. Check if a Volume is mounted on another drive in an Autochanger. - -Autochangers Done: -- 1. Automatic use of more than one drive in an autochanger (done) -- 2. Automatic selection of the correct drive for each Job (i.e. - selects a drive with an appropriate Volume for the Job) (done) -- 6. Allow multiple simultaneous Jobs referencing the same pool write - to several tapes (some new directive(s) are are probably needed for - this) (done) -- Locking (done) -- Key on Storage rather than Pool (done) -- Allow multiple drives to use same Pool (change jobq.c DIR) (done). -- Synchronize multiple drives so that not more - than one loads a tape and any time (done) - - For 1.37: +- Add disk seeking on restore. +- Don't start a second file job if one is already running. +- Add Python writable variable for changing the Priority, + Client, Storage, JobStatus (error), ... +- SD Python + - Solicit Events +- FD Python + - Python script to save with Python, not save, save with Bacula. + - Python script to do backup. +- When Python creates a new label, the tape is immediately + recycled and no label created. This happens when using + autolabeling -- even when Python doesn't generate the name. +- Create a new GUI chapter explaining all the GUI programs. +- Look at Preben's acl.c error handling code. +- Look at adding full Volume and Pool information to a Volume + label so that bscan can get *all* the info. +- Scratch Pool where the volumes can be re-assigned to any Pool. +- Implement Maximum Job Spool Size + +Maybe in 1.37: - By the way: on page http://www.bacula.org/?page=tapedrives , at the bottom, the link to "Tape Testing Chapter" is broken. It goes to /html-manual/... while the others point to /rel-manual/... @@ -88,18 +66,7 @@ For 1.37: a small reference. - Linux Sony LIB-D81, AIT-3 library works. - Device resource needs the "name" of the SD. -- Add and option to see if the file size changed - during backup. -- Implement "update device" from SD so that DIR will - always have current version of device. -- Add disk seeking on restore. -- Add Python writable variable for changing the Priority, - Client, Storage, JobStatus (error), ... -- SD Python - - Solicit Events -- FD Python - - Python script to save with Python, not save, save with Bacula. - - Python script to do backup. +- Add and option to see if the file size changed during 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 @@ -113,17 +80,10 @@ For 1.37: and fix SD messages. - Make sure SD deletes spool files on error exit. - Delete old spool files when SD starts. -- When Python creates a new label, the tape is immediately - recycled and no label created. This happens when using - autolabeling -- even when Python doesn't generate the name. - Add a restore directory-x - When labeling tapes, if you enter 000026, Bacula uses the tape index rather than the Volume name 000026. - Max Vols limit in Pool off by one? -- Look at Preben's acl.c error handling code. -- See multiple-store.txt for Multiple Storage implementation - design. -- Create a new GUI chapter explaining all the GUI programs. - Tell the "restore" user when browsing is no longer possible. - Require restore via the restore command or make a restore Job get the bootstrap file. @@ -131,9 +91,6 @@ For 1.37: - Add offline tape command to Bacula console. - Document that Bootstrap files can be written with cataloging turned off. -- Look at adding full Volume and Pool information to a Volume - label so that bscan can get *all* the info. -- Scratch Pool where the volumes can be re-assigned to any Pool. - Upgrade to MySQL 4.1.1 See: http://dev.mysql.com/doc/mysql/en/Server_SQL_mode.html - Add client version to the Client name line that prints in @@ -203,24 +160,6 @@ Notes: list, also it is maybe a good idea to check for the return value and execute different actions based on the return value -2. Priorities also for the Schedule Resource - - Why: - - With this it is possible to run monthly jobs at the end of the month - instead of the beginning of the next month, so one could define - weekly and monthly pools to be run on Fridays and if there are - 2 Jobs resulting on the same time, the one with the higher priority - takes precedence. This is also helpfull to implement a daily - rotation scheme with an additional 2 weeks changing weekly pool - -Example: - Schedule { - Name = "NightlyBackup" - Run = Priority = 1,Pool=Weekly friday at 21:00 - Run = Priority = 2,Pool=Weekly monthly on friday at 21:00 - Run = Priority = 3,Pool=Weekly yearly on friday at 21:00 - } 3. offline capability to bconsole @@ -280,7 +219,6 @@ Why: ========== - Can one write tapes faster with 8192 byte block sizes? - Specify a single directory to restore. -- Implement Maximum Job Spool Size - Document security problems with the same password for everyone in rpm and Win32 releases. - Browse generations of files. @@ -1283,3 +1221,38 @@ Block Position: 0 - Bootstrap from JobMedia records. - Implement WildFile and WildDir to solve problem of saving only *.doc files. +- Fix + Please use the "label" command to create a new Volume for: + Storage: DDS-4-changer + Media type: + Pool: Default + label + The defined Storage resources are: +- Copy Changer Device and Changer Command from Autochanger + to Device resource in SD if none given in Device resource. +- 1. Automatic use of more than one drive in an autochanger (done) +- 2. Automatic selection of the correct drive for each Job (i.e. + selects a drive with an appropriate Volume for the Job) (done) +- 6. Allow multiple simultaneous Jobs referencing the same pool write + to several tapes (some new directive(s) are are probably needed for + this) (done) +- Locking (done) +- Key on Storage rather than Pool (done) +- Allow multiple drives to use same Pool (change jobq.c DIR) (done). +- Synchronize multiple drives so that not more + than one loads a tape and any time (done) +- 4. Use Changer Device and Changer Command specified in the + Autochanger resource, if none is found in the Device resource. + You can continue to specify them in the Device resource if you want + or need them to be different for each device. +- 5. Implement a new Device directive (perhaps "Autoselect = yes/no") + that can allow a Device be part of an Autochanger, and hence the changer + script protected, but if set to no, will prevent the Device from being + automatically selected from the changer. This allows the device to + be directly accessed through its Device name, but not through the + AutoChanger name. +#6 Select one from among Multiple Storage Devices for Job +#5 Events that call a Python program + (Implemented in Dir/SD) +- Make sure the Device name is in the Query packet returned. + diff --git a/bacula/src/dird/dird_conf.h b/bacula/src/dird/dird_conf.h index 03b14f2d81..ab4e8d1561 100644 --- a/bacula/src/dird/dird_conf.h +++ b/bacula/src/dird/dird_conf.h @@ -127,11 +127,12 @@ public: int num_writers; int max_writers; /* = 1 for files */ int reserved; /* number of reserves */ + int num_drives; /* for autochanger */ + bool autochanger; /* set if device is autochanger */ bool open; bool append; /* in append mode */ bool read; bool labeled; - bool autochanger; bool offline; bool autoselect; uint32_t PoolId; diff --git a/bacula/src/dird/getmsg.c b/bacula/src/dird/getmsg.c index 79a6311722..ae961f3011 100644 --- a/bacula/src/dird/getmsg.c +++ b/bacula/src/dird/getmsg.c @@ -47,6 +47,14 @@ static char *find_msg_start(char *msg); static char Job_status[] = "Status Job=%127s JobStatus=%d\n"; +static char Device_update[] = "DevUpd Job=%127s " + "device=%127s " + "append=%d read=%d num_writers=%d " + "open=%d labeled=%d offline=%d " + "reserved=%d max_writers=%d " + "autoselect=%d autochanger=%d " + "poolid=%lld " + "changer_name=%127s media_type=%127s volume_name=%127s\n"; static char OK_msg[] = "1000 OK\n"; @@ -63,8 +71,18 @@ static char OK_msg[] = "1000 OK\n"; * to the appropriate handler. If the message is * in any other format, it will be returned. * - * E.g. any message beginning with a digit will be returned. - * any message beginning with Jmsg will be processed. + * E.g. any message beginning with a digit will be passed + * through to the caller. + * All other messages are expected begin with some identifier + * -- for the moment only the first character is checked, but + * at a later time, the whole identifier (e.g. Jmsg, CatReq, ...) + * could be checked. This is followed by Job=Jobname + * info. The identifier is used to dispatch the message to the right + * place (Job message, catalog request, ...). The Job is used to lookup + * the JCR so that the action is performed on the correct jcr, and + * the rest of the message is up to the user. Note, DevUpd uses + * *System* for the Job name, and hence no JCR is obtained. This + * is a *rare* case where a jcr is not really needed. * */ int bget_dirmsg(BSOCK *bs) @@ -134,7 +152,9 @@ int bget_dirmsg(BSOCK *bs) Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg); continue; } - if (!(jcr=get_jcr_by_full_name(Job))) { + if (strcmp(Job, "*System*") == 0) { + jcr = NULL; /* No jcr */ + } else if (!(jcr=get_jcr_by_full_name(Job))) { Emsg1(M_ERROR, 0, _("Job not found: %s\n"), bs->msg); continue; } @@ -200,9 +220,61 @@ int bget_dirmsg(BSOCK *bs) char Job[MAX_NAME_LENGTH]; if (sscanf(bs->msg, Job_status, &Job, &JobStatus) == 2) { jcr->SDJobStatus = JobStatus; /* current status */ - free_jcr(jcr); - continue; + } else { + Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg); } + free_jcr(jcr); + continue; + } + /* No JCR for Device Updates! */ + if (bs->msg[0] = 'D') { /* Device update */ + DEVICE *dev; + POOL_MEM dev_name, changer_name, media_type, volume_name; + int dev_open, dev_append, dev_read, dev_labeled; + int dev_offline, dev_autochanger, dev_autoselect; + int dev_num_writers, dev_max_writers, dev_reserved; + uint64_t dev_PoolId; + Dmsg1(100, "msg); + if (sscanf(bs->msg, Device_update, + &Job, dev_name.c_str(), + &dev_append, &dev_read, + &dev_num_writers, &dev_open, + &dev_labeled, &dev_offline, &dev_reserved, + &dev_max_writers, &dev_autoselect, + &dev_autochanger, &dev_PoolId, + changer_name.c_str(), media_type.c_str(), + volume_name.c_str()) != 16) { + Emsg1(M_ERROR, 0, _("Malformed message: %s\n"), bs->msg); + } else { + unbash_spaces(dev_name); + dev = (DEVICE *)GetResWithName(R_DEVICE, dev_name.c_str()); + if (!dev) { + continue; + } + unbash_spaces(changer_name); + unbash_spaces(media_type); + unbash_spaces(volume_name); + bstrncpy(dev->ChangerName, changer_name.c_str(), sizeof(dev->ChangerName)); + bstrncpy(dev->MediaType, media_type.c_str(), sizeof(dev->MediaType)); + bstrncpy(dev->VolumeName, volume_name.c_str(), sizeof(dev->VolumeName)); + /* Note, these are copied because they are boolean rather than + * integer. + */ + dev->open = dev_open; + dev->append = dev_append; + dev->read = dev_read; + dev->labeled = dev_labeled; + dev->offline = dev_offline; + dev->autoselect = dev_autoselect; + dev->autochanger = dev_autochanger > 0; + dev->num_drives = dev_autochanger; /* does double duty */ + dev->PoolId = dev_PoolId; + dev->num_writers = dev_num_writers; + dev->max_writers = dev_max_writers; + dev->reserved = dev_reserved; + dev->found = true; + } + continue; } return n; } diff --git a/bacula/src/dird/msgchan.c b/bacula/src/dird/msgchan.c index 1c49dfc122..233b30fbc1 100644 --- a/bacula/src/dird/msgchan.c +++ b/bacula/src/dird/msgchan.c @@ -49,13 +49,6 @@ static char query_device[] = "query device=%s"; /* Response from Storage daemon */ static char OKjob[] = "3000 OK Job SDid=%d SDtime=%d Authorization=%100s\n"; static char OK_device[] = "3000 OK use device device=%s\n"; -static char OK_query[] = "3001 OK query " - "append=%d read=%d num_writers=%d " - "open=%d labeled=%d offline=%d " - "reserved=%d max_writers=%d " - "autoselect=%d autochanger=%d " - "poolid=%lld " - "changer_name=%127s media_type=%127s volume_name=%127s"; /* Storage Daemon requests */ static char Job_start[] = "3010 Job %127s start\n"; @@ -108,9 +101,7 @@ bool connect_to_storage_daemon(JCR *jcr, int retry_interval, */ bool update_device_res(JCR *jcr, DEVICE *dev) { - POOL_MEM device_name, changer_name, media_type, volume_name; - int dev_open, dev_append, dev_read, dev_labeled; - int dev_offline, dev_autochanger, dev_autoselect; + POOL_MEM device_name; BSOCK *sd; if (!connect_to_storage_daemon(jcr, 5, 30, 0)) { return false; @@ -120,36 +111,8 @@ bool update_device_res(JCR *jcr, DEVICE *dev) bash_spaces(device_name); bnet_fsend(sd, query_device, device_name.c_str()); Dmsg1(100, ">stored: %s\n", sd->msg); - if (bget_dirmsg(sd) > 0) { - Dmsg1(100, "msg); - if (sscanf(sd->msg, OK_query, - &dev_append, &dev_read, - &dev->num_writers, &dev_open, - &dev_labeled, &dev_offline, &dev->reserved, - &dev->max_writers, &dev_autoselect, - &dev_autochanger, &dev->PoolId, - changer_name.c_str(), media_type.c_str(), - volume_name.c_str()) != 14) { - return false; - } - unbash_spaces(changer_name); - unbash_spaces(media_type); - unbash_spaces(volume_name); - bstrncpy(dev->ChangerName, changer_name.c_str(), sizeof(dev->ChangerName)); - bstrncpy(dev->MediaType, media_type.c_str(), sizeof(dev->MediaType)); - bstrncpy(dev->VolumeName, volume_name.c_str(), sizeof(dev->VolumeName)); - /* Note, these are copied because they are boolean rather than - * integer. - */ - dev->open = dev_open; - dev->append = dev_append; - dev->read = dev_read; - dev->labeled = dev_labeled; - dev->offline = dev_offline; - dev->autoselect = dev_autoselect; - dev->autochanger = dev_autochanger; - dev->found = true; - } else { + /* The data is returned through Device_update */ + if (bget_dirmsg(sd) <= 0) { return false; } return true; diff --git a/bacula/src/lib/jcr.c b/bacula/src/lib/jcr.c index 6b95c32167..01b8c85bff 100755 --- a/bacula/src/lib/jcr.c +++ b/bacula/src/lib/jcr.c @@ -204,7 +204,7 @@ JCR *new_jcr(int size, JCR_free_HANDLER *daemon_free_jcr) jcr->errmsg = get_pool_memory(PM_MESSAGE); jcr->errmsg[0] = 0; /* Setup some dummy values */ - jcr->Job[0] = 0; /* no job name by default */ + bstrncpy(jcr->Job, "*System*", sizeof(jcr->Job)); jcr->JobId = 0; jcr->JobType = JT_SYSTEM; /* internal job until defined */ jcr->JobLevel = L_NONE; diff --git a/bacula/src/stored/askdir.c b/bacula/src/stored/askdir.c index 461b60b96a..6d7465c482 100644 --- a/bacula/src/stored/askdir.c +++ b/bacula/src/stored/askdir.c @@ -42,6 +42,14 @@ static char Create_job_media[] = "CatReq Job=%s CreateJobMedia" " StartBlock=%u EndBlock=%u\n"; static char FileAttributes[] = "UpdCat Job=%s FileAttributes "; static char Job_status[] = "Status Job=%s JobStatus=%d\n"; +static char Device_update[] = "DevUpd Job=%s device=%s " + "append=%d read=%d num_writers=%d " + "open=%d labeled=%d offline=%d " + "reserved=%d max_writers=%d " + "autoselect=%d autochanger=%d " + "poolid=%s " + "changer_name=%s media_type=%s volume_name=%s\n"; + /* Responses received from the Director */ @@ -58,6 +66,76 @@ static char OK_create[] = "1000 OK CreateJobMedia\n"; /* Forward referenced functions */ static int wait_for_sysop(DCR *dcr); +/* Send update information about a device to Director */ +bool dir_update_device(JCR *jcr, DEVICE *dev) +{ + BSOCK *dir = jcr->dir_bsock; + POOL_MEM dev_name, VolumeName, MediaType, ChangerName; + DEVRES *device = dev->device; + bool ok; + char ed1[50]; + + pm_strcpy(dev_name, device->hdr.name); + bash_spaces(dev_name); + if (dev->is_labeled()) { + pm_strcpy(VolumeName, dev->VolHdr.VolName); + } else { + pm_strcpy(VolumeName, "*"); + } + bash_spaces(VolumeName); + pm_strcpy(MediaType, device->media_type); + bash_spaces(MediaType); + if (device->changer_res) { + pm_strcpy(ChangerName, device->changer_res->hdr.name); + bash_spaces(ChangerName); + } else { + pm_strcpy(ChangerName, "*"); + } + ok =bnet_fsend(dir, Device_update, + jcr->Job, + dev_name.c_str(), + dev->can_append()!=0, + dev->can_read()!=0, dev->num_writers, + dev->is_open()!=0, dev->is_labeled()!=0, + dev->is_offline()!=0, dev->reserved_device, + dev->is_tape()?100000:1, + dev->autoselect, 0, + edit_uint64(dev->PoolId, ed1), + ChangerName.c_str(), MediaType.c_str(), VolumeName.c_str()); + Dmsg1(100, ">dird: %s\n", dir->msg); + return ok; +} + +bool dir_update_changer(JCR *jcr, AUTOCHANGER *changer) +{ + BSOCK *dir = jcr->dir_bsock; + POOL_MEM dev_name, MediaType; + DEVRES *device; + bool ok; + + pm_strcpy(dev_name, changer->hdr.name); + bash_spaces(dev_name); + device = (DEVRES *)changer->device->first(); + pm_strcpy(MediaType, device->media_type); + bash_spaces(MediaType); + /* This is mostly to indicate that we are here */ + ok = bnet_fsend(dir, Device_update, + jcr->Job, + dev_name.c_str(), /* Changer name */ + 0, 0, 0, /* append, read, num_writers */ + 0, 0, 0, /* is_open, is_labeled, offline */ + 0, 0, /* reserved, max_writers */ + 0, /* Autoselect */ + changer->device->size(), /* Number of devices */ + "0", /* PoolId */ + "*", /* ChangerName */ + MediaType.c_str(), /* MediaType */ + "*"); /* VolName */ + Dmsg1(100, ">dird: %s\n", dir->msg); + return ok; +} + + /* * Send current JobStatus to Director */ diff --git a/bacula/src/stored/job.c b/bacula/src/stored/job.c index a99dbb7b40..a6600c2ab1 100644 --- a/bacula/src/stored/job.c +++ b/bacula/src/stored/job.c @@ -54,14 +54,9 @@ static char NO_device[] = "3924 Device \"%s\" not in SD Device resources.\n"; static char NOT_open[] = "3925 Device \"%s\" could not be opened or does not exist.\n"; static char BAD_use[] = "3913 Bad use command: %s\n"; static char BAD_job[] = "3915 Bad Job command: %s\n"; -static char OK_query[] = "3001 OK query " - "append=%d read=%d num_writers=%d " - "open=%d labeled=%d offline=%d " - "reserved=%d max_writers=%d " - "autoselect=%d autochanger=%d " - "poolid=%s " - "changer_name=%s media_type=%s volume_name=%s"; -static char BAD_query[] = "3917 Bad query command: %s\n"; +static char OK_query[] = "3001 OK query\n"; +static char NO_query[] = "3918 Query failed\n"; +static char BAD_query[] = "3917 Bad query command: %s\n"; /* * Director requests us to start a job @@ -425,12 +420,11 @@ static bool use_device_cmd(JCR *jcr) */ bool query_cmd(JCR *jcr) { - POOL_MEM dev_name; + POOL_MEM dev_name, VolumeName, MediaType, ChangerName; BSOCK *dir = jcr->dir_bsock; DEVRES *device; AUTOCHANGER *changer; bool ok; - char ed1[50]; Dmsg1(100, "Query_cmd: %s", dir->msg); ok = sscanf(dir->msg, query_device, dev_name.c_str()) == 1; @@ -447,33 +441,13 @@ bool query_cmd(JCR *jcr) if (!device->dev) { break; } - DEVICE *dev = device->dev; - POOL_MEM VolumeName, MediaType, ChangerName; UnlockRes(); - if (dev->is_labeled()) { - pm_strcpy(VolumeName, dev->VolHdr.VolName); + ok = dir_update_device(jcr, device->dev); + if (ok) { + ok = bnet_fsend(dir, OK_query); } else { - pm_strcpy(VolumeName, "*"); + bnet_fsend(dir, NO_query); } - bash_spaces(VolumeName); - pm_strcpy(MediaType, device->media_type); - bash_spaces(MediaType); - if (device->changer_res) { - pm_strcpy(ChangerName, device->changer_res->hdr.name); - bash_spaces(ChangerName); - } else { - pm_strcpy(ChangerName, "*"); - } - ok =bnet_fsend(dir, OK_query, - dev->can_append()!=0, - dev->can_read()!=0, dev->num_writers, - dev->is_open()!=0, dev->is_labeled()!=0, - dev->is_offline()!=0, dev->reserved_device, - dev->is_tape()?100000:1, - dev->autoselect, 0, - edit_uint64(dev->PoolId, ed1), - ChangerName.c_str(), MediaType.c_str(), VolumeName.c_str()); - Dmsg1(100, ">dird: %s\n", dir->msg); return ok; } } @@ -481,15 +455,15 @@ bool query_cmd(JCR *jcr) /* Find resource, and make sure we were able to open it */ if (fnmatch(dev_name.c_str(), changer->hdr.name, 0) == 0) { UnlockRes(); - /* This is mostly to indicate that we are here */ - ok = bnet_fsend(dir, OK_query, - 0, 0, 0, /* append, read, num_writers */ - 0, 0, 0, /* is_open, is_labeled, offline */ - 0, 0, /* reserved, max_writers */ - 0, 1, /* autoselect, AutoChanger = 1 */ - "0", /* PoolId */ - "*", "*", "*"); /* ChangerName, MediaType, VolName */ - Dmsg1(100, ">dird: %s\n", dir->msg); + if (!changer->device || changer->device->size() == 0) { + continue; /* no devices */ + } + ok = dir_update_changer(jcr, changer); + if (ok) { + ok = bnet_fsend(dir, OK_query); + } else { + bnet_fsend(dir, NO_query); + } return ok; } } diff --git a/bacula/src/stored/protos.h b/bacula/src/stored/protos.h index 00c1379fb3..820fda9bd0 100644 --- a/bacula/src/stored/protos.h +++ b/bacula/src/stored/protos.h @@ -28,182 +28,184 @@ uint32_t new_VolSessionId(); /* From acquire.c */ -bool reserve_device_for_append(JCR *jcr, DEVICE *dev); -DCR *acquire_device_for_append(JCR *jcr, DEVICE *dev); -bool reserve_device_for_read(JCR *jcr, DEVICE *dev); -DCR *acquire_device_for_read(JCR *jcr, DEVICE *dev); -bool release_device(DCR *dcr); -DCR *new_dcr(JCR *jcr, DEVICE *dev); -void free_dcr(DCR *dcr); +bool reserve_device_for_append(JCR *jcr, DEVICE *dev); +DCR *acquire_device_for_append(JCR *jcr, DEVICE *dev); +bool reserve_device_for_read(JCR *jcr, DEVICE *dev); +DCR *acquire_device_for_read(JCR *jcr, DEVICE *dev); +bool release_device(DCR *dcr); +DCR *new_dcr(JCR *jcr, DEVICE *dev); +void free_dcr(DCR *dcr); /* From askdir.c */ enum get_vol_info_rw { GET_VOL_INFO_FOR_WRITE, GET_VOL_INFO_FOR_READ }; -bool dir_get_volume_info(DCR *dcr, enum get_vol_info_rw); -bool dir_find_next_appendable_volume(DCR *dcr); -bool dir_update_volume_info(DCR *dcr, bool label); -bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr); -bool dir_ask_sysop_to_mount_volume(DCR *dcr); -bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec); -bool dir_send_job_status(JCR *jcr); -bool dir_create_jobmedia_record(DCR *dcr); +bool dir_get_volume_info(DCR *dcr, enum get_vol_info_rw); +bool dir_find_next_appendable_volume(DCR *dcr); +bool dir_update_volume_info(DCR *dcr, bool label); +bool dir_ask_sysop_to_create_appendable_volume(DCR *dcr); +bool dir_ask_sysop_to_mount_volume(DCR *dcr); +bool dir_update_file_attributes(DCR *dcr, DEV_RECORD *rec); +bool dir_send_job_status(JCR *jcr); +bool dir_create_jobmedia_record(DCR *dcr); +bool dir_update_device(JCR *jcr, DEVICE *dev); +bool dir_update_changer(JCR *jcr, AUTOCHANGER *changer); /* authenticate.c */ -int authenticate_director(JCR *jcr); -int authenticate_filed(JCR *jcr); +int authenticate_director(JCR *jcr); +int authenticate_filed(JCR *jcr); /* From autochanger.c */ -int autoload_device(DCR *dcr, int writing, BSOCK *dir); -bool autochanger_list(DCR *dcr, BSOCK *dir); -void mark_volume_not_inchanger(DCR *dcr); -char *edit_device_codes(DCR *dcr, char *omsg, const char *cmd); +int autoload_device(DCR *dcr, int writing, BSOCK *dir); +bool autochanger_list(DCR *dcr, BSOCK *dir); +void mark_volume_not_inchanger(DCR *dcr); +char *edit_device_codes(DCR *dcr, char *omsg, const char *cmd); /* From block.c */ -void dump_block(DEV_BLOCK *b, const char *msg); +void dump_block(DEV_BLOCK *b, const char *msg); DEV_BLOCK *new_block(DEVICE *dev); DEV_BLOCK *dup_block(DEV_BLOCK *eblock); -void init_block_write(DEV_BLOCK *block); -void empty_block(DEV_BLOCK *block); -void free_block(DEV_BLOCK *block); -bool write_block_to_device(DCR *dcr); -bool write_block_to_dev(DCR *dcr); -void print_block_read_errors(JCR *jcr, DEV_BLOCK *block); -void ser_block_header(DEV_BLOCK *block); +void init_block_write(DEV_BLOCK *block); +void empty_block(DEV_BLOCK *block); +void free_block(DEV_BLOCK *block); +bool write_block_to_device(DCR *dcr); +bool write_block_to_dev(DCR *dcr); +void print_block_read_errors(JCR *jcr, DEV_BLOCK *block); +void ser_block_header(DEV_BLOCK *block); #define CHECK_BLOCK_NUMBERS true #define NO_BLOCK_NUMBER_CHECK false -bool read_block_from_device(DCR *dcr, bool check_block_numbers); -bool read_block_from_dev(DCR *dcr, bool check_block_numbers); +bool read_block_from_device(DCR *dcr, bool check_block_numbers); +bool read_block_from_dev(DCR *dcr, bool check_block_numbers); /* From butil.c -- utilities for SD tool programs */ -void print_ls_output(const char *fname, const char *link, int type, struct stat *statp); +void print_ls_output(const char *fname, const char *link, int type, struct stat *statp); JCR *setup_jcr(const char *name, char *dev_name, BSR *bsr, - const char *VolumeName, int mode); -void display_tape_error_status(JCR *jcr, DEVICE *dev); + const char *VolumeName, int mode); +void display_tape_error_status(JCR *jcr, DEVICE *dev); /* From dev.c */ -DEVICE *init_dev(JCR *jcr, DEVICE *dev, DEVRES *device); -int open_dev(DEVICE *dev, char *VolName, int mode); -off_t lseek_dev(DEVICE *dev, off_t offset, int whence); -int open_first_part(DEVICE *dev); -int open_next_part(DEVICE *dev); -int open_guess_name_dev(DEVICE *dev); -void close_dev(DEVICE *dev); -void force_close_dev(DEVICE *dev); -bool truncate_dev(DEVICE *dev); -void term_dev(DEVICE *dev); -char * strerror_dev(DEVICE *dev); -void clrerror_dev(DEVICE *dev, int func); -bool update_pos_dev(DEVICE *dev); -bool rewind_dev(DEVICE *dev); -bool load_dev(DEVICE *dev); -bool offline_dev(DEVICE *dev); -int flush_dev(DEVICE *dev); -int weof_dev(DEVICE *dev, int num); -int write_block(DEVICE *dev); +DEVICE *init_dev(JCR *jcr, DEVICE *dev, DEVRES *device); +int open_dev(DEVICE *dev, char *VolName, int mode); +off_t lseek_dev(DEVICE *dev, off_t offset, int whence); +int open_first_part(DEVICE *dev); +int open_next_part(DEVICE *dev); +int open_guess_name_dev(DEVICE *dev); +void close_dev(DEVICE *dev); +void force_close_dev(DEVICE *dev); +bool truncate_dev(DEVICE *dev); +void term_dev(DEVICE *dev); +char * strerror_dev(DEVICE *dev); +void clrerror_dev(DEVICE *dev, int func); +bool update_pos_dev(DEVICE *dev); +bool rewind_dev(DEVICE *dev); +bool load_dev(DEVICE *dev); +bool offline_dev(DEVICE *dev); +int flush_dev(DEVICE *dev); +int weof_dev(DEVICE *dev, int num); +int write_block(DEVICE *dev); uint32_t status_dev(DEVICE *dev); -int eod_dev(DEVICE *dev); -bool fsf_dev(DEVICE *dev, int num); -bool fsr_dev(DEVICE *dev, int num); -bool bsf_dev(DEVICE *dev, int num); -bool bsr_dev(DEVICE *dev, int num); -void attach_jcr_to_device(DEVICE *dev, JCR *jcr); -void detach_jcr_from_device(DEVICE *dev, JCR *jcr); -JCR *next_attached_jcr(DEVICE *dev, JCR *jcr); -bool dev_can_write(DEVICE *dev); -bool offline_or_rewind_dev(DEVICE *dev); -bool reposition_dev(DEVICE *dev, uint32_t file, uint32_t block); -void init_dev_wait_timers(DEVICE *dev); -bool double_dev_wait_time(DEVICE *dev); +int eod_dev(DEVICE *dev); +bool fsf_dev(DEVICE *dev, int num); +bool fsr_dev(DEVICE *dev, int num); +bool bsf_dev(DEVICE *dev, int num); +bool bsr_dev(DEVICE *dev, int num); +void attach_jcr_to_device(DEVICE *dev, JCR *jcr); +void detach_jcr_from_device(DEVICE *dev, JCR *jcr); +JCR *next_attached_jcr(DEVICE *dev, JCR *jcr); +bool dev_can_write(DEVICE *dev); +bool offline_or_rewind_dev(DEVICE *dev); +bool reposition_dev(DEVICE *dev, uint32_t file, uint32_t block); +void init_dev_wait_timers(DEVICE *dev); +bool double_dev_wait_time(DEVICE *dev); /* Get info about device */ -char * dev_name(DEVICE *dev); -char * dev_vol_name(DEVICE *dev); +char * dev_name(DEVICE *dev); +char * dev_vol_name(DEVICE *dev); uint32_t dev_block(DEVICE *dev); uint32_t dev_file(DEVICE *dev); -bool dev_is_tape(DEVICE *dev); +bool dev_is_tape(DEVICE *dev); /* From device.c */ -bool open_device(DCR *dcr); -bool first_open_device(DEVICE *dev); -bool fixup_device_block_write_error(DCR *dcr); -void _lock_device(const char *file, int line, DEVICE *dev); -void _unlock_device(const char *file, int line, DEVICE *dev); -void _block_device(const char *file, int line, DEVICE *dev, int state); -void _unblock_device(const char *file, int line, DEVICE *dev); -void _steal_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *hold, int state); -void _give_back_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *hold); -void set_new_volume_parameters(DCR *dcr); -void set_new_file_parameters(DCR *dcr); -bool device_is_unmounted(DEVICE *dev); -void dev_lock(DEVICE *dev); -void dev_unlock(DEVICE *dev); +bool open_device(DCR *dcr); +bool first_open_device(DEVICE *dev); +bool fixup_device_block_write_error(DCR *dcr); +void _lock_device(const char *file, int line, DEVICE *dev); +void _unlock_device(const char *file, int line, DEVICE *dev); +void _block_device(const char *file, int line, DEVICE *dev, int state); +void _unblock_device(const char *file, int line, DEVICE *dev); +void _steal_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *hold, int state); +void _give_back_device_lock(const char *file, int line, DEVICE *dev, bsteal_lock_t *hold); +void set_new_volume_parameters(DCR *dcr); +void set_new_file_parameters(DCR *dcr); +bool device_is_unmounted(DEVICE *dev); +void dev_lock(DEVICE *dev); +void dev_unlock(DEVICE *dev); const char *edit_blocked_reason(DEVICE *dev); /* From dircmd.c */ -void *handle_connection_request(void *arg); +void *handle_connection_request(void *arg); /* From fd_cmds.c */ -void run_job(JCR *jcr); -bool bootstrap_cmd(JCR *jcr); +void run_job(JCR *jcr); +bool bootstrap_cmd(JCR *jcr); /* From job.c */ -void stored_free_jcr(JCR *jcr); -void connection_from_filed(void *arg); -void handle_filed_connection(BSOCK *fd, char *job_name); +void stored_free_jcr(JCR *jcr); +void connection_from_filed(void *arg); +void handle_filed_connection(BSOCK *fd, char *job_name); /* From label.c */ -int read_dev_volume_label(DCR *dcr); -int read_dev_volume_label_guess(DCR *dcr, bool write); -void create_session_label(DCR *dcr, DEV_RECORD *rec, int label); -void create_volume_label(DEVICE *dev, const char *VolName, const char *PoolName); -bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName, const char *PoolName); -bool write_ansi_ibm_label(DCR *dcr, const char *VolName); -int read_ansi_ibm_label(DCR *dcr); -bool write_session_label(DCR *dcr, int label); -bool write_volume_label_to_block(DCR *dcr); -bool rewrite_volume_label(DCR *dcr, bool recycle); -void dump_volume_label(DEVICE *dev); -void dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose); -bool unser_volume_label(DEVICE *dev, DEV_RECORD *rec); -bool unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec); +int read_dev_volume_label(DCR *dcr); +int read_dev_volume_label_guess(DCR *dcr, bool write); +void create_session_label(DCR *dcr, DEV_RECORD *rec, int label); +void create_volume_label(DEVICE *dev, const char *VolName, const char *PoolName); +bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName, const char *PoolName); +bool write_ansi_ibm_label(DCR *dcr, const char *VolName); +int read_ansi_ibm_label(DCR *dcr); +bool write_session_label(DCR *dcr, int label); +bool write_volume_label_to_block(DCR *dcr); +bool rewrite_volume_label(DCR *dcr, bool recycle); +void dump_volume_label(DEVICE *dev); +void dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose); +bool unser_volume_label(DEVICE *dev, DEV_RECORD *rec); +bool unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec); /* From match_bsr.c */ -int match_bsr(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec, - SESSION_LABEL *sesrec); -int match_bsr_block(BSR *bsr, DEV_BLOCK *block); -void position_bsr_block(BSR *bsr, DEV_BLOCK *block); -BSR *find_next_bsr(BSR *root_bsr, DEVICE *dev); -bool match_set_eof(BSR *bsr, DEV_RECORD *rec); +int match_bsr(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec, + SESSION_LABEL *sesrec); +int match_bsr_block(BSR *bsr, DEV_BLOCK *block); +void position_bsr_block(BSR *bsr, DEV_BLOCK *block); +BSR *find_next_bsr(BSR *root_bsr, DEVICE *dev); +bool match_set_eof(BSR *bsr, DEV_RECORD *rec); /* From mount.c */ -bool mount_next_write_volume(DCR *dcr, bool release); -bool mount_next_read_volume(DCR *dcr); -void release_volume(DCR *ddr); -void mark_volume_in_error(DCR *dcr); +bool mount_next_write_volume(DCR *dcr, bool release); +bool mount_next_read_volume(DCR *dcr); +void release_volume(DCR *ddr); +void mark_volume_in_error(DCR *dcr); /* From parse_bsr.c */ -BSR *parse_bsr(JCR *jcr, char *lf); -void dump_bsr(BSR *bsr, bool recurse); -void free_bsr(BSR *bsr); +BSR *parse_bsr(JCR *jcr, char *lf); +void dump_bsr(BSR *bsr, bool recurse); +void free_bsr(BSR *bsr); VOL_LIST *new_vol(); -int add_vol(JCR *jcr, VOL_LIST *vol); -void free_vol_list(JCR *jcr); -void create_vol_list(JCR *jcr); +int add_vol(JCR *jcr, VOL_LIST *vol); +void free_vol_list(JCR *jcr); +void create_vol_list(JCR *jcr); /* From record.c */ const char *FI_to_ascii(int fi); const char *stream_to_ascii(int stream, int fi); -bool write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec); -bool can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec); -bool read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec); +bool write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec); +bool can_write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec); +bool read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec); DEV_RECORD *new_record(); -void free_record(DEV_RECORD *rec); -void empty_record(DEV_RECORD *rec); +void free_record(DEV_RECORD *rec); +void empty_record(DEV_RECORD *rec); /* From read_record.c */ bool read_records(DCR *dcr, @@ -211,12 +213,12 @@ bool read_records(DCR *dcr, bool mount_cb(DCR *dcr)); /* From spool.c */ -bool begin_data_spool (DCR *dcr); -bool discard_data_spool (DCR *dcr); -bool commit_data_spool (DCR *dcr); -bool are_attributes_spooled (JCR *jcr); -bool begin_attribute_spool (JCR *jcr); -bool discard_attribute_spool (JCR *jcr); -bool commit_attribute_spool (JCR *jcr); -bool write_block_to_spool_file (DCR *dcr); -void list_spool_stats (BSOCK *bs); +bool begin_data_spool (DCR *dcr); +bool discard_data_spool (DCR *dcr); +bool commit_data_spool (DCR *dcr); +bool are_attributes_spooled (JCR *jcr); +bool begin_attribute_spool (JCR *jcr); +bool discard_attribute_spool (JCR *jcr); +bool commit_attribute_spool (JCR *jcr); +bool write_block_to_spool_file (DCR *dcr); +void list_spool_stats (BSOCK *bs); diff --git a/bacula/src/stored/stored.c b/bacula/src/stored/stored.c index a774a46e2f..3bd86b0fbf 100644 --- a/bacula/src/stored/stored.c +++ b/bacula/src/stored/stored.c @@ -249,6 +249,8 @@ uint32_t newVolSessionId() /* Check Configuration file for necessary info */ static void check_config() { + AUTOCHANGER *changer; + LockRes(); me = (STORES *)GetNextRes(R_STORAGE, NULL); if (!me) { @@ -256,7 +258,6 @@ static void check_config() Jmsg1(NULL, M_ERROR_TERM, 0, _("No Storage resource defined in %s. Cannot continue.\n"), configfile); } - my_name_is(0, (char **)NULL, me->hdr.name); /* Set our real name */ if (GetNextRes(R_STORAGE, (RES *)me) != NULL) { @@ -284,14 +285,40 @@ static void check_config() close_msg(NULL); /* close temp message handler */ init_msg(NULL, me->messages); /* open daemon message handler */ - UnlockRes(); if (!me->working_directory) { Jmsg1(NULL, M_ERROR_TERM, 0, _("No Working Directory defined in %s. Cannot continue.\n"), configfile); } - set_working_directory(me->working_directory); + + /* Ensure that the media_type for each device is the same */ + foreach_res(changer, R_AUTOCHANGER) { + DEVRES *device; + char *media_type = NULL; + foreach_alist(device, changer->device) { + if (media_type == NULL) { + media_type = device->media_type; + continue; + } + if (strcmp(media_type, device->media_type) != 0) { + Jmsg(NULL, M_ERROR_TERM, 0, + _("Media Type not the same for all devices in changer %s. Cannot continue.\n"), + changer->hdr.name); + } + /* + * If the device does not have a changer name or changer command + * defined, used the one from the Autochanger resource + */ + if (!device->changer_name) { + device->changer_name = bstrdup(changer->changer_name); + } + if (!device->changer_command) { + device->changer_command = bstrdup(changer->changer_command); + } + } + } + UnlockRes(); } /* diff --git a/bacula/src/stored/stored_conf.c b/bacula/src/stored/stored_conf.c index a776b492c1..a1c3d00dc8 100644 --- a/bacula/src/stored/stored_conf.c +++ b/bacula/src/stored/stored_conf.c @@ -140,8 +140,8 @@ static RES_ITEM changer_items[] = { {"name", store_name, ITEM(res_changer.hdr.name), 0, ITEM_REQUIRED, 0}, {"description", store_str, ITEM(res_changer.hdr.desc), 0, 0, 0}, {"device", store_alist_res, ITEM(res_changer.device), R_DEVICE, ITEM_REQUIRED, 0}, - {"changerdevice", store_strname, ITEM(res_changer.changer_name), 0, 0, 0}, - {"changercommand", store_strname, ITEM(res_changer.changer_command), 0, 0, 0}, + {"changerdevice", store_strname, ITEM(res_changer.changer_name), 0, ITEM_REQUIRED, 0}, + {"changercommand", store_strname, ITEM(res_changer.changer_command), 0, ITEM_REQUIRED, 0}, {NULL, NULL, 0, 0, 0, 0} }; @@ -160,7 +160,7 @@ RES_TABLE resources[] = { {"device", dev_items, R_DEVICE}, {"messages", msgs_items, R_MSGS}, {"autochanger", changer_items, R_AUTOCHANGER}, - {NULL, NULL, 0} + {NULL, NULL, 0} }; @@ -178,7 +178,7 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm return; } sendit(sock, "dump_resource type=%d\n", type); - if (type < 0) { /* no recursion */ + if (type < 0) { /* no recursion */ type = - type; recurse = 0; } @@ -188,40 +188,40 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm break; case R_STORAGE: sendit(sock, "Storage: name=%s SDaddr=%s SDport=%d SDDport=%d HB=%s\n", - res->res_store.hdr.name, - NPRT(get_first_address(res->res_store.sdaddrs, buf, sizeof(buf))), - get_first_port_host_order(res->res_store.sdaddrs), - get_first_port_host_order(res->res_store.sddaddrs), - edit_utime(res->res_store.heartbeat_interval, buf, sizeof(buf))); + res->res_store.hdr.name, + NPRT(get_first_address(res->res_store.sdaddrs, buf, sizeof(buf))), + get_first_port_host_order(res->res_store.sdaddrs), + get_first_port_host_order(res->res_store.sddaddrs), + edit_utime(res->res_store.heartbeat_interval, buf, sizeof(buf))); if (res->res_store.sdaddrs) { - foreach_dlist(p, res->res_store.sdaddrs) { + foreach_dlist(p, res->res_store.sdaddrs) { sendit(sock, " SDaddr=%s SDport=%d\n", - p->get_address(buf, sizeof(buf)), p->get_port_host_order()); - } + p->get_address(buf, sizeof(buf)), p->get_port_host_order()); + } } if (res->res_store.sddaddrs) { - foreach_dlist(p, res->res_store.sddaddrs) { + foreach_dlist(p, res->res_store.sddaddrs) { sendit(sock, " SDDaddr=%s SDDport=%d\n", - p->get_address(buf, sizeof(buf)), p->get_port_host_order()); - } + p->get_address(buf, sizeof(buf)), p->get_port_host_order()); + } } break; case R_DEVICE: sendit(sock, "Device: name=%s MediaType=%s Device=%s LabelType=%d\n", - res->res_dev.hdr.name, - res->res_dev.media_type, res->res_dev.device_name, - res->res_dev.label_type); + res->res_dev.hdr.name, + res->res_dev.media_type, res->res_dev.device_name, + res->res_dev.label_type); sendit(sock, " rew_wait=%d min_bs=%d max_bs=%d\n", - res->res_dev.max_rewind_wait, res->res_dev.min_block_size, - res->res_dev.max_block_size); + res->res_dev.max_rewind_wait, res->res_dev.min_block_size, + res->res_dev.max_block_size); sendit(sock, " max_jobs=%d max_files=%" lld " max_size=%" lld "\n", - res->res_dev.max_volume_jobs, res->res_dev.max_volume_files, - res->res_dev.max_volume_size); + res->res_dev.max_volume_jobs, res->res_dev.max_volume_files, + res->res_dev.max_volume_size); sendit(sock, " max_file_size=%" lld " capacity=%" lld "\n", - res->res_dev.max_file_size, res->res_dev.volume_capacity); + res->res_dev.max_file_size, res->res_dev.volume_capacity); sendit(sock, " spool_directory=%s\n", NPRT(res->res_dev.spool_directory)); sendit(sock, " max_spool_size=%" lld " max_job_spool_size=%" lld "\n", - res->res_dev.max_spool_size, res->res_dev.max_job_spool_size); + res->res_dev.max_spool_size, res->res_dev.max_job_spool_size); if (res->res_dev.changer_res) { sendit(sock, " changer=%p\n", res->res_dev.changer_res); } @@ -271,8 +271,8 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm case R_AUTOCHANGER: DEVRES *dev; sendit(sock, "Changer: name=%s Changer_devname=%s\n Changer_cmd=%s\n", - res->res_changer.hdr.name, - res->res_changer.changer_name, res->res_changer.changer_command); + res->res_changer.hdr.name, + res->res_changer.changer_name, res->res_changer.changer_command); foreach_alist(dev, res->res_changer.device) { sendit(sock, " --->Device: name=%s\n", dev->hdr.name); } @@ -322,81 +322,81 @@ void free_resource(RES *sres, int type) switch (type) { case R_DIRECTOR: if (res->res_dir.password) { - free(res->res_dir.password); + free(res->res_dir.password); } if (res->res_dir.address) { - free(res->res_dir.address); + free(res->res_dir.address); } break; case R_AUTOCHANGER: if (res->res_changer.changer_name) { - free(res->res_changer.changer_name); + free(res->res_changer.changer_name); } if (res->res_changer.changer_command) { - free(res->res_changer.changer_command); + free(res->res_changer.changer_command); } if (res->res_changer.device) { - delete res->res_changer.device; + delete res->res_changer.device; } break; case R_STORAGE: if (res->res_store.sdaddrs) { - free_addresses(res->res_store.sdaddrs); + free_addresses(res->res_store.sdaddrs); } if (res->res_store.sddaddrs) { - free_addresses(res->res_store.sddaddrs); + free_addresses(res->res_store.sddaddrs); } if (res->res_store.working_directory) { - free(res->res_store.working_directory); + free(res->res_store.working_directory); } if (res->res_store.pid_directory) { - free(res->res_store.pid_directory); + free(res->res_store.pid_directory); } if (res->res_store.subsys_directory) { - free(res->res_store.subsys_directory); + free(res->res_store.subsys_directory); } break; case R_DEVICE: if (res->res_dev.media_type) { - free(res->res_dev.media_type); + free(res->res_dev.media_type); } if (res->res_dev.device_name) { - free(res->res_dev.device_name); + free(res->res_dev.device_name); } if (res->res_dev.changer_name) { - free(res->res_dev.changer_name); + free(res->res_dev.changer_name); } if (res->res_dev.changer_command) { - free(res->res_dev.changer_command); + free(res->res_dev.changer_command); } if (res->res_dev.alert_command) { - free(res->res_dev.alert_command); + free(res->res_dev.alert_command); } if (res->res_dev.spool_directory) { - free(res->res_dev.spool_directory); + free(res->res_dev.spool_directory); } if (res->res_dev.mount_point) { - free(res->res_dev.mount_point); + free(res->res_dev.mount_point); } if (res->res_dev.mount_command) { - free(res->res_dev.mount_command); + free(res->res_dev.mount_command); } if (res->res_dev.unmount_command) { - free(res->res_dev.unmount_command); + free(res->res_dev.unmount_command); } if (res->res_dev.write_part_command) { - free(res->res_dev.write_part_command); + free(res->res_dev.write_part_command); } if (res->res_dev.free_space_command) { - free(res->res_dev.free_space_command); + free(res->res_dev.free_space_command); } break; case R_MSGS: if (res->res_msgs.mail_cmd) { - free(res->res_msgs.mail_cmd); + free(res->res_msgs.mail_cmd); } if (res->res_msgs.operator_cmd) { - free(res->res_msgs.operator_cmd); + free(res->res_msgs.operator_cmd); } free_msgs_res((MSGS *)res); /* free message resource */ res = NULL; @@ -430,10 +430,10 @@ void save_resource(int type, RES_ITEM *items, int pass) */ for (i=0; items[i].name; i++) { if (items[i].flags & ITEM_REQUIRED) { - if (!bit_is_set(i, res_all.res_dir.hdr.item_present)) { + if (!bit_is_set(i, res_all.res_dir.hdr.item_present)) { Emsg2(M_ERROR_TERM, 0, _("\"%s\" item is required in \"%s\" resource, but not found.\n"), - items[i].name, resources[rindex]); - } + items[i].name, resources[rindex]); + } } /* If this triggers, take a look at lib/parse_conf.h */ if (i >= MAX_RES_ITEMS) { @@ -454,49 +454,49 @@ void save_resource(int type, RES_ITEM *items, int pass) case R_DIRECTOR: case R_DEVICE: case R_MSGS: - break; + break; /* Resources containing a resource or an alist */ case R_STORAGE: - if ((res = (URES *)GetResWithName(R_STORAGE, res_all.res_dir.hdr.name)) == NULL) { + if ((res = (URES *)GetResWithName(R_STORAGE, res_all.res_dir.hdr.name)) == NULL) { Emsg1(M_ERROR_TERM, 0, "Cannot find Storage resource \"%s\"\n", res_all.res_dir.hdr.name); - } - res->res_store.messages = res_all.res_store.messages; - break; + } + res->res_store.messages = res_all.res_store.messages; + break; case R_AUTOCHANGER: - if ((res = (URES *)GetResWithName(type, res_all.res_changer.hdr.name)) == NULL) { + if ((res = (URES *)GetResWithName(type, res_all.res_changer.hdr.name)) == NULL) { Emsg1(M_ERROR_TERM, 0, "Cannot find AutoChanger resource %s\n", - res_all.res_changer.hdr.name); - } - /* we must explicitly copy the device alist pointer */ - res->res_changer.device = res_all.res_changer.device; - /* - * Now update each device in this resource to point back - * to the changer resource. - */ - foreach_alist(dev, res->res_changer.device) { - dev->changer_res = (AUTOCHANGER *)&res->res_changer; - } - if ((errstat = pthread_mutex_init(&res->res_changer.changer_mutex, NULL)) != 0) { - berrno be; + res_all.res_changer.hdr.name); + } + /* we must explicitly copy the device alist pointer */ + res->res_changer.device = res_all.res_changer.device; + /* + * Now update each device in this resource to point back + * to the changer resource. + */ + foreach_alist(dev, res->res_changer.device) { + dev->changer_res = (AUTOCHANGER *)&res->res_changer; + } + if ((errstat = pthread_mutex_init(&res->res_changer.changer_mutex, NULL)) != 0) { + berrno be; Jmsg1(NULL, M_ERROR_TERM, 0, _("Unable to init mutex: ERR=%s\n"), - be.strerror(errstat)); - } - break; + be.strerror(errstat)); + } + break; default: printf("Unknown resource type %d\n", type); - error = 1; - break; + error = 1; + break; } if (res_all.res_dir.hdr.name) { - free(res_all.res_dir.hdr.name); - res_all.res_dir.hdr.name = NULL; + free(res_all.res_dir.hdr.name); + res_all.res_dir.hdr.name = NULL; } if (res_all.res_dir.hdr.desc) { - free(res_all.res_dir.hdr.desc); - res_all.res_dir.hdr.desc = NULL; + free(res_all.res_dir.hdr.desc); + res_all.res_dir.hdr.desc = NULL; } return; } @@ -504,45 +504,45 @@ void save_resource(int type, RES_ITEM *items, int pass) /* The following code is only executed on pass 1 */ switch (type) { case R_DIRECTOR: - size = sizeof(DIRRES); - break; + size = sizeof(DIRRES); + break; case R_STORAGE: - size = sizeof(STORES); - break; + size = sizeof(STORES); + break; case R_DEVICE: - size = sizeof(DEVRES); - break; + size = sizeof(DEVRES); + break; case R_MSGS: - size = sizeof(MSGS); - break; + size = sizeof(MSGS); + break; case R_AUTOCHANGER: - size = sizeof(AUTOCHANGER); - break; + size = sizeof(AUTOCHANGER); + break; default: printf("Unknown resource type %d\n", type); - error = 1; - size = 1; - break; + error = 1; + size = 1; + break; } /* Common */ if (!error) { res = (URES *)malloc(size); memcpy(res, &res_all, size); if (!res_head[rindex]) { - res_head[rindex] = (RES *)res; /* store first entry */ + res_head[rindex] = (RES *)res; /* store first entry */ } else { - RES *next; - /* Add new res to end of chain */ - for (next=res_head[rindex]; next->next; next=next->next) { - if (strcmp(next->name, res->res_dir.hdr.name) == 0) { - Emsg2(M_ERROR_TERM, 0, + RES *next; + /* Add new res to end of chain */ + for (next=res_head[rindex]; next->next; next=next->next) { + if (strcmp(next->name, res->res_dir.hdr.name) == 0) { + Emsg2(M_ERROR_TERM, 0, _("Attempt to define second \"%s\" resource named \"%s\" is not permitted.\n"), - resources[rindex].name, res->res_dir.hdr.name); - } - } - next->next = (RES *)res; + resources[rindex].name, res->res_dir.hdr.name); + } + } + next->next = (RES *)res; Dmsg2(90, "Inserting %s res: %s\n", res_to_str(type), - res->res_dir.hdr.name); + res->res_dir.hdr.name); } } } diff --git a/bacula/src/stored/stored_conf.h b/bacula/src/stored/stored_conf.h index 8ac96e14cd..9ea5d71bad 100644 --- a/bacula/src/stored/stored_conf.h +++ b/bacula/src/stored/stored_conf.h @@ -30,7 +30,7 @@ enum { R_MSGS, R_AUTOCHANGER, R_FIRST = R_DIRECTOR, - R_LAST = R_AUTOCHANGER /* keep this updated */ + R_LAST = R_AUTOCHANGER /* keep this updated */ }; enum { @@ -45,29 +45,29 @@ enum { /* Definition of the contents of each Resource */ class DIRRES { public: - RES hdr; + RES hdr; - char *password; /* Director password */ - char *address; /* Director IP address or zero */ - int enable_ssl; /* Use SSL with this Director */ - int monitor; /* Have only access to status and .status functions */ + char *password; /* Director password */ + char *address; /* Director IP address or zero */ + int enable_ssl; /* Use SSL with this Director */ + int monitor; /* Have only access to status and .status functions */ }; /* Storage daemon "global" definitions */ class s_res_store { public: - RES hdr; + RES hdr; dlist *sdaddrs; dlist *sddaddrs; - char *working_directory; /* working directory for checkpoints */ + char *working_directory; /* working directory for checkpoints */ char *pid_directory; char *subsys_directory; - int require_ssl; /* Require SSL on all connections */ + int require_ssl; /* Require SSL on all connections */ uint32_t max_concurrent_jobs; /* maximum concurrent jobs to run */ - MSGS *messages; /* Daemon message handler */ - utime_t heartbeat_interval; /* Interval to send hb to FD */ + MSGS *messages; /* Daemon message handler */ + utime_t heartbeat_interval; /* Interval to send hb to FD */ }; typedef struct s_res_store STORES; @@ -75,52 +75,52 @@ class AUTOCHANGER { public: RES hdr; alist *device; - char *changer_name; /* Changer device name */ - char *changer_command; /* Changer command -- external program */ + 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: - RES hdr; - - char *media_type; /* User assigned media type */ - char *device_name; /* Archive device name */ - char *changer_name; /* Changer device name */ - char *changer_command; /* Changer command -- external program */ - char *alert_command; /* Alert command -- external program */ - char *spool_directory; /* Spool file directory */ - int label_type; /* label type */ - int autoselect; /* Automatically select from AutoChanger */ - uint32_t drive_index; /* Autochanger drive index */ - uint32_t cap_bits; /* Capabilities of this device */ - uint32_t max_changer_wait; /* Changer timeout */ - uint32_t max_rewind_wait; /* maximum secs to wait for rewind */ - uint32_t max_open_wait; /* maximum secs to wait for open */ - uint32_t max_open_vols; /* maximum simultaneous open volumes */ - uint32_t min_block_size; /* min block size */ - uint32_t max_block_size; /* max block size */ - uint32_t max_volume_jobs; /* max jobs to put on one volume */ + RES hdr; + + char *media_type; /* User assigned media type */ + char *device_name; /* Archive device name */ + char *changer_name; /* Changer device name */ + char *changer_command; /* Changer command -- external program */ + char *alert_command; /* Alert command -- external program */ + char *spool_directory; /* Spool file directory */ + int label_type; /* label type */ + int autoselect; /* Automatically select from AutoChanger */ + uint32_t drive_index; /* Autochanger drive index */ + uint32_t cap_bits; /* Capabilities of this device */ + uint32_t max_changer_wait; /* Changer timeout */ + uint32_t max_rewind_wait; /* maximum secs to wait for rewind */ + uint32_t max_open_wait; /* maximum secs to wait for open */ + uint32_t max_open_vols; /* maximum simultaneous open volumes */ + uint32_t min_block_size; /* min block size */ + uint32_t max_block_size; /* max block size */ + uint32_t max_volume_jobs; /* max jobs to put on one volume */ uint32_t max_network_buffer_size; /* max network buf size */ - utime_t vol_poll_interval; /* interval between polling volume during mount */ - int64_t max_volume_files; /* max files to put on one volume */ - int64_t max_volume_size; /* max bytes to put on one volume */ - int64_t max_file_size; /* max file size in bytes */ - int64_t volume_capacity; /* advisory capacity */ - int64_t max_spool_size; /* Max spool size for all jobs */ - int64_t max_job_spool_size; /* Max spool size for any single job */ + utime_t vol_poll_interval; /* interval between polling volume during mount */ + int64_t max_volume_files; /* max files to put on one volume */ + int64_t max_volume_size; /* max bytes to put on one volume */ + int64_t max_file_size; /* max file size in bytes */ + int64_t volume_capacity; /* advisory capacity */ + int64_t max_spool_size; /* Max spool size for all jobs */ + int64_t max_job_spool_size; /* Max spool size for any single job */ - int64_t max_part_size; /* Max part size */ - char *mount_point; /* Mount point for require mount devices */ - char *mount_command; /* Mount command */ - char *unmount_command; /* Unmount command */ - char *write_part_command; /* Write part command */ - char *free_space_command; /* Free space command */ + int64_t max_part_size; /* Max part size */ + char *mount_point; /* Mount point for require mount devices */ + char *mount_command; /* Mount command */ + char *unmount_command; /* Unmount command */ + 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 */ + DEVICE *dev; /* Pointer to phyical dev -- set at runtime */ + AUTOCHANGER *changer_res; /* pointer to changer res if any */ }; @@ -130,5 +130,5 @@ union URES { DEVRES res_dev; MSGS res_msgs; AUTOCHANGER res_changer; - RES hdr; + RES hdr; }; diff --git a/bacula/src/version.h b/bacula/src/version.h index c1c4f7f117..b5103f49b6 100644 --- a/bacula/src/version.h +++ b/bacula/src/version.h @@ -1,8 +1,8 @@ /* */ #undef VERSION #define VERSION "1.37.6" -#define BDATE "06 March 2005" -#define LSMDATE "06Mar05" +#define BDATE "07 March 2005" +#define LSMDATE "07Mar05" /* Debug flags */ #undef DEBUG -- 2.39.5