This chapter provides a tutorial to DCP programming, and includes the following topics:
Section 6.1 decribes DCP programming.
Section 6.2, talks about starting up a control program.
Section 6.3, describes DCP subroutine libraries.
Section 6.4, discusses sample source code layout.
Section 6.5, presents tables of OpenVault tokens for a DCP.
A DCP (drive control program) translates between the OpenVault ADI and the actual device control interface for its drive, and between device responses and ADI/R. The DCP does what is necessary to affect the required ADI semantics. It keeps the MLM server's cache (persistent store) up to date regarding DCP configuration, drive configuration, and ready state information. To do this, the DCP sends config and ready commands when it detects changes in state, on a best-effort basis.
Currently, the drive configuration and state is moved in one direction only, from a DCP to the MLM server persistent store. The MLM server uses this information to assist with drive selection for cartridge and volume mounts. In future revisions of OpenVault, the DCP may recover some state from the persistent store, so that configuration and state information can flow in both directions. However, the DCP and drive are always considered the authoritative source for state information about a DCP or its drive.
In sample implementations, DCP configuration is stored in a configuration file that is local to each DCP. See Section 6.2.1, for more information.
Each DCP must initialize itself in order to contact the MLM server.
Drives may be connected to multiple hosts and thus have multiple control paths. There can be one DCP associated with each control path. Only one DCP at a time may be active for any drive; the MLM server arbitrates which DCP is active.
For example, a DCP could be on the inactive side of a multiconnected library. The DCP boot sequence must not interfere with the active side of a multiconnected library. The MLM server is the arbitrator of control for multiconnected libraries and drives. A DCP should not assume that it is controlling a drive until the MLM server says so.
Each DCP should have a configuration file containing at least the following information:
Address of the controlling MLM server: This allows the DCP to initiate contact with the controlling MLM server. It is the name of the system, or its numeric IP address. The MLM server is usually available at well-known port number on that system, by default 44444.
OpenVault name for the managed drive: The MLM server uses this name as an identifier for this physical drive. This is the name of the device that it is managing, not the name of the particular instance of DCP. All names must be unique within an OpenVault domain so that the server can detect multiconnected libraries (multiple LCPs controlling the same library).
DCP instance name: The instance name is arbitrary, but is required for cases where there are multiconnected libraries.
Control path to the drive: This is how a DCP talks to the hardware (for example, /dev/rmt/tps0d3). This information is not visible to the MLM server. Some drives are not controlled in this way (VHS videocassette players, for instance), but all DCP implementations need something equivalent.
List of access mode names and access capabilities for this drive : Although implementation-dependent, a way is needed for administrators to control the capabilities that a DCP advertises to the server. In IRIX implementations, the DCP configuration file, such as shown in Example 6-1, is used. It lists drive names and associated capabilities, which are string tokens. The OpenVault server compares these tokens for equality when looking for drives to satisfy user requests.
All lines would be prefaced with “cap” in this example:
name type cartridge shorthand capacity device pathname slot type 7base DLT DLT7000 DLT7000 35000 /dev/rmt/tps3d5.7000 DLT7000 capabilities 7s DLT DLT7000 DLT7000s 35000 /dev/rmt/tps3d5s.7000 DLT7000 capabilities 7nr DLT DLT7000 DLT7000 35000 /dev/rmt/tps3d5nr.7000 DLT7000 capabilities 7nrs DLT DLT7000 DLT7000s 35000 /dev/rmt/tps3d5nrs.7000 DLT7000 capabilities 7c DLT DLT7000 DLT7000c 70000 /dev/rmt/tps3d5.7000c DLT7000 capabilities 7sc DLT DLT7000 DLT7000cs 70000 /dev/rmt/tps3d5s.7000c DLT7000 capabilities 7nrc DLT DLT7000 DLT7000c 70000 /dev/rmt/tps3d5nr.7000c DLT7000 capabilities 7nrsc DLT DLT7000 DLT7000cs 70000 /dev/rmt/tps3d5nrs.7000c DLT7000 capabilities 7v DLT DLT7000 DLT7000 35000 /dev/rmt/tps3d5v.7000 DLT7000 capabilities 7sv DLT DLT7000 DLT7000s 35000 /dev/rmt/tps3d5sv.7000 DLT7000 capabilities 7nrv DLT DLT7000 DLT7000 35000 /dev/rmt/tps3d5nrv.7000 DLT7000 capabilities 7nrsv DLT DLT7000 DLT7000s 35000 /dev/rmt/tps3d5nrsv.7000 DLT7000 capabilities 7vc DLT DLT7000 DLT7000c 70000 /dev/rmt/tps3d5v.7000c DLT7000 capabilities 7svc DLT DLT7000 DLT7000cs 70000 /dev/rmt/tps3d5sv.7000c DLT7000 capabilities 7nrvc DLT DLT7000 DLT7000c 70000 /dev/rmt/tps3d5nrv.7000c DLT7000 capabilities 7nrsvc DLT DLT7000 DLT7000cs 70000 /dev/rmt/tps3d5nrsv.7000c DLT7000 capabilities |
A UNIX device pathname is included so as to avoid having the DCP understand the format of a dev_t minor number, or equivalent. The DCP can replicate the path (copy dev_t) when it needs to create a handle for that combination of drive and access mode. OpenVault defines the default capabilities of a drive, and the DCP specifies what capabilities it offers in terms of changes to that default set.
For easy editing, DCP configuration files should be composed of readable ASCII text.
The DCP boot sequence is composed of the following steps:
When a DCP boots or reboots, it does the following:
Allocates internal data structures and initialize state.
Refrains from talking to the drive.
The DCP boots into activate disable state, and must wait for the MLM server to tell it when to talk to the drive. If the drive is dual-ported with another DCP actively controlling it, that session should not be interrupted!
The MLM server issues an activate enable command when conditions permit your DCP to control the drive. If the library is single-ported, activate enable is issued almost immediately.
Reads its configuration file.
Establishes a session with the MLM server.
The DCP sends the hello message upon opening the connection. In this example, name is the OpenVault name for the drive, and inst is the DCP instance name. If connection fails, retry every two minutes. The DCP blocks until it receives a welcome command telling it which language version to use during this session.
hello language["ADI"] version["1.0"] client["name"] instance ["inst"]; |
When the MLM server is first contacted by a DCP, it does the following:
Integrates the drive into its list of managed devices.
The MLM server checks for other DCPs managing that physical drive. If this DCP is the first, OpenVault allows this DCP to proceed. This sequencing implies that DCPs are given control of their associated drive on a first-come-first-served basis.
(Eventually) issues an activate enable command to the DCP.
When the MLM server says to activate enable, the DCP does the following:
Replies to the MLM server with a ready no command.
The DCP informs the MLM server that it has started to come up, but is not yet ready to accept drive control commands.
Talks to the drive to determine:
That the drive is supported by this DCP.
The supported media formats (for example: EXABYTE-8mm-5GB).
Whether or not the drive can support the listed access modes.
If the drive is loaded or in use at this time.
Any other information that may be relevant to drive or DCP operation.
Collects any state or configuration information from the MLM server.
The DCP can store state or configuration information in the OpenVault persistent store.
Push all the capability information up into the MLM server.
The DCP needs to update the MLM server's copy of the capability list at boot time, before the DCP has been activated. This is different from an LCP, which must be activated in all cases. By contrast, it is unnecessary to activate all the DCPs that might control a given drive just to determine their capability set.
The DCP takes all its compiled-in settings and information from its configuration file to generate a config command for the MLM server. There is a possibility that the offered capabilities might change once the DCP has had a chance to talk to the drive hardware, but the MLM server must deal with this if it happens.
Sends a ready command to the MLM server.
The DCP is now ready to accept drive control commands.
Responds success to the original activate enable command.
This is defined to be the last step as a convenience to the MLM server, so that the server can block until it receives a response from its activate enable command rather than continually polling for arrival of the ready command.
When the MLM server gets a successful response to activate enable, it sends the DCP its message logging level.
When a DCP receives an activate enable command from the MLM server, and the DCP is in ready lost state, it performs these steps:
Accesses its drive to acquire or verify device-specific configuration and state.
For example, a DCP may consult its drive to determine:
If the drive is supported by this DCP
Whether the drive is in a usable state for this DCP
Optimal block size
Pushes configuration information to the MLM server.
For example, configuration information includes: supported form factors, media types, bit formats, media capacity, block size, nominal drive load time, drive read and write bandwidth, and drive capabilities. See the tables in the section Section 6.5, for particulars.
Transitions to ready state, and pushes this new state to MLM server.
The infrastructure developer's kit includes a framework for writing a DCP that helps ease the development, porting, and maintenance effort for DCPs. This section describes the general source tree layout.
OpenVault clients and servers communicate with a custom interprocess communication (IPC) layer. DCP modules that deal directly with ADI and ADI/R need to include the following header file, and be loaded with the following C library:
ovsrc/src.LGPL/include/ov_lib.h | |
C data structures, macros, and subroutine prototypes for IPC | |
ovsrc/src.LGPL/comm/libov_comm.a | |
C library containing IPC subroutines |
OpenVault includes language parsers and generators. DCP modules using these facilities need to include the following header files, and be loaded with the following C libraries:
ovsrc/src.LGPL/include/adi.h | |
Supported ADI and ADI/R language version, ADI standard errors, and C data structures for ADI and ADI/R command representation | |
ovsrc/src.LGPL/include/dcp.h | |
Parser and generator subroutine prototypes | |
ovsrc/src.LGPL/include/hello.h | |
C data structures for HELLO and WELCOME command representation | |
ovsrc/src.LGPL/hellor/libov_hello.a | |
C library that contains HELLO parser-generator subroutines | |
ovsrc/src.LGPL/adi/libov_adi.a | |
C library that contains ADI parser-generator subroutines |
The DCP(3) man page documents the ADI and ADI/R lexical library routines that you employ when writing a DCP. Table 6-1 offers a summary of these routines.
Table 6-1. ADI and ADI/R Lexical Library Routines
Purpose of Activity | DCP Function | Short Description |
---|---|---|
To initiate session with MLM server | Begins session with a specific MLM server, including HELLO version negotiation. | |
To parse ADI command from MLM server | Parses an ADI command and returns an ADI command structure. | |
To acknowledge ADI command | Informs MLM server that the DCP received an ADI command. | |
To send ADI/R command to MLM server | ADIR_alloc_cmd() ADIR_alloc_ready() ADIR_alloc_message() ADIR_alloc_capinfo() | Allocates ADIR command structure. Allocates ADIR ready structure. Allocates memory for ADIR message. Puts drive capability info into ADIR capinfo. Allocates attribute name and value pair. |
To send final response for ADI command to MLM server | ADIR_alloc_response() ADI_alloc_string() ADIR_send() | Allocates ADIR response structure. Allocates string and links into ADI stringlist. Transmits ADIR command to MLM server. Deallocates ADIR command structure. |
To free ADI command | Deallocates ADI command structure. |
The infrastructure developer's kit includes common utility code for writing a DCP. To use this code, include the following header files, and read the following C module:
ovsrc/src.LGPL/include/cctxt.h | |
Generic command queuing mechanism | |
ovsrc/src.LGPL/include/dcp_lib.h | |
Generic representation of DCP and drive state, generic representation of an attribute, common DCP fixed and programmable entry points, and common DCP utility subroutine prototypes | |
ovsrc/src.LGPL/server/include/queue.h | |
Generic queue and linked list implementation | |
ovsrc/clients/src.LGPL/dcp/common/util.c | |
DCP common fixed-entry points and utility subroutines |
Much of a DCP's representation of DCP and drive state can be represented generically. However, the DCP developer needs a way to customize this representation for a particular drive and implementation.
The framework provides a private data area and programmable entry points so the developer can customize the representation of DCP and drive state. The private data area allows the developer to maintain additional information about the DCP and drive; programmable entry points allow the developer to customize actions associated with initialization (booting), deactivation (transition to ready lost state), and shutdown. This arrangement allows the shared framework to invoke these entry points as appropriate.
Example 6-2 shows the framework's generic representation for a drive:
Example 6-2. Framework's Generic Representation
struct driveinfo { /* elements from DCP config file. */ char *client; /* MLM name of this drive. */ char *instance; /* Client instance. */ char *mlmhost; /* MLM host. */ int mlmport; /* MLM port. */ int timeout; /* ADI receive timeout. */ char *addr; /* Drive access path for DCP. */ /* elements initiated by DCP. */ enum ADIR_ready_type readystatus; /* ready, not r_, disconnected */ enum ADIR_msg_severity loglevel; /* Log level for DCP messages. */ char *vendor; /* Drive vendor name. */ queue_t ADI_cmd_queue; /* ADI command queue. */ queue_t ADIR_cmd_queue; /* ADIR command queue. */ int waiting_for_ack; /* 1 if waiting for ack, or 0 */ char *taskid_for_ack; /* TaskID of last ADIR command */ void(*dcp_deactivate)(struct driveinfo *drivei); /* deactivate */ void(*dcp_exit)(*drivei, int abnormal); /* shutdown */ void(*dcp_dispatch)(*drivei, struct ADI_command *cmd); char *(*dcp_taskid)(*drivei); /* taskid generation */ void *private; /* DCP private libary info */ }; |
A DCP that makes use of this developer framework must call the dcp_init subroutine, shown in Example 6-3, to initialize the generic and private data areas for DCP and drive information, and set the programmable DCP entry points:
Example 6-3. dcp_init Subroutine
void dcp_init(struct driveinfo *drivei, void dcp_init_private(), void dcp_deactivate(), void dcp_exit(), void dcp_dispatch(), void dcp_taskid()); |
This entry point is called one time only from dcp_init(); so the driveinfo structure does not store it. Required entry point for DCP private data area allocation and initialization:
void dcp_init_private(struct driveinfo *drivei); |
Remaining entry points are stored in the libinfo structure. Required entry point for DCP private actions to activate disable:
void dcp_deactivate(struct driveinfo *drivei); |
Required entry point for DCP private actions to shut down gracefully and exit:
void dcp_exit(struct driveinfo *drivei); |
Required entry point for ADI command dispatch from within command state machine:
void dcp_dispatch(struct driveinfo *drivei, struct ADI_command *cmd); |
Required entry point for DCP to generate a task ID for ADI/R commands:
void char *dcp_taskid(struct driveinfo *drivei); |
The following functions are provided for ADI command queuing and the state machine:
The following functions are provided for ADI/R command queuing and MLM server acknowledgment processing:
The following function is provided for DCP ready state processing:
The following functions are provided for handling ADI error responses:
void attribute_error() | |
Handles attribute or show error. | |
void ready_error() | |
Handles ready state error. |
The following functions are provided for mandatory attribute and show processing:
The following functions are provided for debugging:
The EXB-8505XL drive is a SCSI-2 tape device that accepts 8 mm media.
The DCP for an EXABYTE 8505XL drive may be used in combination with the LCP for an EXABYTE 210 media changer.
Control access is three-part, and includes use of the local filesystem, a pass-through SCSI driver, and IRIX magnetic tape interface (MTIO) ioctl() operations.
This implementation uses a set of drive instance prototypes, which are represented by a set of existing device special files, for example /dev/rmt/tps0d6. So drive instances are already instantiated. Attach and detach commands simply bind a drive handle to an existing instance, or device special file. Creating and removing a binding is done using the local filesystem mknod() and unlink() operations.
Calls to the pass-through SCSI driver are made with the IRIX C library for generic SCSI operations; see the dslib(3X) man page. Direct SCSI access is by means of this device special file:
/dev/scsi/scCdUlL |
In this filename, C is the SCSI controller number, U is the unit number, and L is the logical unit number (lun) for accessing drive control. This information may be determined on IRIX systems by using the hinv command.
Calls to dslib are used to get mode sense information directly from the drive, to check for information such as whether the drive supports partitions, and to issue mode select commands, such as those for moving the tape to a particular position.
This section describes the DCP source and run-time configuration modules.
Example 6-4 illustrates the ovsrc/clients/dcp/EXB-8505XL/config file, which describes traits of the drive and MLM server.
Example 6-4. ovsrc/clients/dcp/EXB-8505XL/config File
localhost # MLM server host name 739 # MLM server TCP socket fred # OpenVault name for drive dcpfred # DCP instance name /dev/rmt/tps0d6 # MTIO drive control access path /dev/scsi/sc0d610 # SCSI drive control access path 60 # Communications timeout |
Remaining lines include supported drive instance prototypes, including mode name, form factor, media type, bit format, capacity, and control capabilities.
The ovsrc/clients/dcp/EXB-8505XL/config.c module parses this file and fills in drive information in both the DCP generic and private data areas.
The ovsrc/clients/dcp/EXB-8505XL/control.h header file contains definitions, data type declarations, and subroutine prototypes for control access by means of the pass-through SCSI driver; see the dslib(3X) man page.
The ovsrc/clients/dcp/EXB-8505XL/control.c module contains convenience routines that make SCSI library calls to get mode sense, check for partition support, and change tape partition. Since partition support is currently not implemented, the latter is nonoperational.
Otherwise, device access is made directly from the main ADI semantic module by means of MTIO ioctl() operations.
This layer, named after its many functions starting with “do,” is where a DCP interprets ADI commands. The programmer customizes this layer, based on the generic drive methods that are provided as part of the DCP developer framework.
The ovsrc/clients/dcp/EXB-8505XL/main.h header file contains the DCP private data area portion of a generic drive representation, as well as macros and subroutine prototypes, including four programmable DCP entry points for use by the framework and semantic support routines.
The ovsrc/clients/dcp/EXB-8505XL/main.c module is where ADI semantic handling routines and entry points are implemented, and where ADI commands are dispatched to the appropriate semantic handling routine. For example, the ADI_load command would be dispatched to the do_load() function.
There is potential for a single, shared SCSI-2 DCP. An additional device module would be required only for vendor-dependent processing, or for departures from the standard.
More thought and changes to ADI and the DCP framework are needed to support non host-attached devices, such as broadcast video.
The infrastructure developer's kit was developed on IRIX systems, and has yet to be ported to other platforms. The DCP framework does not yet support partitions.
This section documents the predefined strings that are relevant to DCP development.
OpenVault assumes that there is default set of drive capabilities. Table 6-2 shows the tokens that describe changes from a standard drive.
Table 6-2. Predefined mount Tokens
Token | Description |
---|---|
audio | Mount point allows playing audio data from media (often unimplemented). |
compression | Attempts compression of the data stream. |
fixed | Blocks on the media are a fixed size. |
readonly | The mount point allows reading of the media. |
readwrite | The mount point allow writing of the media. |
rewind | Rewinds the media on close of the mount point. |
status | A status-only mount point is also created (in a directory created for the session). |
variable | Blocks on the media are variable sized. |
Drive capabilities are entirely extensible; so this list is not exhaustive.
For a list of predefined cartridge form factors, see Section 4.5.1 in Chapter 4.
The format of bits recorded on media is independent of external cartridge appearance. One well-known case is the EXABYTE 8200 versus EXABYTE 8500 format, both being recorded on 8 mm media.
Table 6-3 shows tokens for each bit format, what form factors use it, and a description of how the format is generated.
Table 6-3. Predefined Bit Format Tokens
Token | Form Factor | Description |
---|---|---|
8200 | 8 mm | EXABYTE 8200 native |
8200c | 8 mm | EXABYTE 8200 compressed |
8500 | 8 mm | EXABYTE 8500 native |
8500c | 8 mm | EXABYTE 8500 compressed |
mammoth | 8 mm | EXABYTE mammoth native |
mammothc | 8 mm | EXABYTE mammoth compressed |
3480 | 3480 | 3480 native |
3490 | 3480 | 3490 native |
3490E | 3480 | 3490E native |
3495 | 3480 | IBM Magstar native |
4480 | 3480 | STK TimberLine native |
4490 | 3480 | STK RedWood native |
DLT2000 | DLT | DLT2000 native |
DLT2000c | DLT | DLT2000 compressed |
DTL4000 | DLT | DLT4000 native |
DLT4000c | DLT | DLT4000 compressed |
DLT7000 | DLT | DLT7000 native |
DLT7000c | DLT | DLT7000 compressed |
DDS1 | DAT | Digital data storage 1.3 GB |
DDS2 | DAT | Digital data storage 2.0 GB |
DDS3 | DAT | Digital data storage 4.0 GB |
D2 | D2-[SML] | Ampex DST-310 |
DTF | DTF | Sony GY-10 |
QIC80 | QIC | Quarter-inch cartridge 80 MB |
QIC100 | QIC | Quarter-inch cartridge 100 MB |
QIC150 | QIC | Quarter-inch cartridge 150 MB |
QIC525 | QIC | Quarter-inch cartridge 525 MB |
QIC1024 | QIC | Quarter-inch cartridge 1024 MB |
ISO9660 | CD-ROM | DOS-like (8.3) filesystem on CD-ROM |
Table 6-4 shows tokens used to describe media inside a cartridge.
Table 6-4. Predefined Media Type Tokens
Token | Product Name or Description |
---|---|
8mm-12m | 12 meter 8 mm |
8mm-60m | 60 meter 8 mm |
8mm-90m | 90 meter 8 mm |
8mm-112m | 112 meter 8 mm |
8mm-160m | 160 meter 8 mm |
mammoth | EXABYTE mammoth |
3480 | IBM 3480 |
3490 | IBM 3490 |
3490E | IBM 3490E |
3495 | IBM Magstar native |
4480 | STK TimberLine native |
4490 | STK RedWood native |
DLT2000 | Quantum DLT2000 |
DLT2000XT | Quantum DLT2000XT |
DLT4000 | Quantum DLT4000 |
DLT7000 | Quantum DLT7000 |
DDS1 | DAT 60 meter |
DDS2 | DAT 90 meter |
DDS3 | DAT 120 meter |
D2-S | Ampex DST-310 small format |
D2-M | Ampex DST-310 medium format |
D2-L | Ampex DST-310 165GB large format |
DTF | Sony GY-10 |
QIC | Quarter-inch cartridge tape |
ISO9660 | CD-ROM |
The ADI interface assumes that there is a standard set of names used for partitioned media. Table 6-5 shows the tokens used for naming partitions.
Table 6-5. Predefined Partition Name Tokens
Token | Description |
---|---|
PART 1 | The first partition on the media. For magneto-optical or two-sided optical disc, this would be side one or side A. |
PART 2 | The second partition on the media. On linear media such as a tape, PART 2 immediately follows PART 1. On non-linear media such as a disk, PART 2 is the second-lowest numbered or lettered partition. Note that PART 2 does not refer to the next partition that is in use, it refers to the next partition. |
Table 6-6 shows attributes used in OpenVault, where they are used, and what they mean.
Table 6-6. Predefined Attribute Name Tokens (DCP)
Attribute Name | Where Used | Possible Values | Required? | Description |
---|---|---|---|---|
ADI config command, perf clause | Numeric, in bytes per second | Yes | The total effective bandwidth that an application should be able to sustain when reading from that drive using the given capability set. | |
ADI config command, perf clause | Numeric, in bytes per second | Yes | The total effective bandwith that an application should be able to sustain when writing to that drive using the given capability set. | |
ADI config command, perf clause | Numeric, in bytes | Yes | The total storage capacity of the cartridge that an application should be able to expect when accessing that drive using the given capability set. | |
ADI config command, perf clause | Numeric, in bytes | Yes | The I/O size that would best use the drive/cartridge combination with that drive with the given capability set. | |
ADI config command, perf clause | Numeric, in seconds | Yes | The number of seconds between the time a cartridge is first inserted into a drive and the time that the drive is ready to read/write data. | |
ADI config command, config clause | Cartridge FormFactor token ( Table 4-2) | Yes | A supported form factor when the drive is using the given capability set. | |
ADI config command, config clause | MediaType token | Yes | A supported media type, usually indicating tape length. | |
ADI config command, config clause | Bit Format token | Yes | A supported recording format when the drive is using the given capability set. | |
ALI config command, perf clause | Numeric, in seconds | Yes | Approximate time it takes for the library to move a cartridge from its home location to a drive, or back, not including drive load/unload time. This is analogous to “nominal seek time” of a disk drive. It is defined as the total real time to execute a large number of cartridge move-load operations randomly spread through the physical space of a library, divided by the number of such operations performed. |