You're an 8-Track Kind of Guy -
Implementing the Tape Recording Subsystem

May 15, 1995

I had some thoughts about the Tape Recording Subsystem after our meeting that I wanted to share with you. The following subjects are discussed below:

Tape Library - expands on the ideas you and Stan kicked about.
Control Server - presents a suggested implementation of a custom control server.
Tcl-based GUIs - reveals how to simplify GUI development.

Tape Library

The tape library would be a library of open()-close()-read()-write() functions that clients could call to access a tape drive. Internally, a _TapeDrive structure would be defined that contains information about an opened tape "file":

    typedef  struct  _TapeDrive {
    }  _TapeDrive ;

The clients would only see a TapeDrive handle:

    typedef  struct  _TapeDrive  *TapeDrive ;

A client would access a tape drive with calls such as the following:

    TapeDrive  tape ;             	/* Handle for opened drive. */

    status = tpOpen ("drive[@host][/file]", options, &tape) ;

    status = tpRead (tape, numBytesToRead, buffer, &numBytesRead) ;

    status = tpWrite (tape, numBytesToWrite, buffer, &numBytesWritten) ;

    fd = tpFd (tape, controlOrData) ;

    status = tpClose (tape, options) ;

The "file" name passed to tpOpen() specifies the desired drive, the host to which the drive is attached, and the name of the file to access. For example,


("triplex" and the second "ampex" specify the IP addresses of the respective controllers.) The host name and file name are optional; defaults can be supplied in various ways when needed.

The options passed to tpOpen() and tpClose() are simply character strings containing UNIX command-line style options for the open and close operations; e.g.,

    tpOpen ("ampex", "-recordSize 1024 -numRecords 10000", &tape) ;

    tpClose (tape, "-rewind") ;

By using this mechanism for specifying options, new options can be added as needed without affecting existing client code. (We have a library package to parse the options.)

The tpFd() function returns a file descriptor for an opened tape's control or data channel (e.g., the control socket or the FDDI read and write sockets). These might be needed by GUI clients such as TPCE. Some other tape library calls may be necessary to allow asynchronous I/O of commands and status.

Internally, the tape library could use either the rsh(1) implementation or the control server implementation. The client would not need to know which, except with regard to the file descriptor returned by tpFd() for the control channel.

Custom Control Server

If you decide to write a custom control server, don't - we already have one. My gentle program is a network server that provides a separate Tcl interpreter to each of its connected clients. (A more detailed description of gentle is appended to this memo.) Tcl (Tool Command Language) is an embedded command language that can be extended with application-specific commands; e.g., tape drive commands. Although gentle simultaneously supports multiple clients, restricting it to one client would provide us with the locking mechanism we need to ensure exclusive access to a tape drive.

A Tcl-based program like gentle has the following advantages:

Communicating with the Control Server

Clients send Tcl commands to gentle as ASCII strings encoded in Sun's External Data Representation (XDR). gentle interprets the commands and sends responses back, also as XDR ASCII strings. (TPOCC, incidentally, uses this same protocol to communicate between processes.) Sending and receiving XDR ASCII strings is very simple, thanks to our Xnet library. The following example sends a tape command to the control server and reads the response:

    #include  <stdio.h>           	-- Standard I/O definitions.
    #include  "tcp_util.h"        	-- TCP/IP networking utilities.
    #include  "xnet_util.h"       	-- XNET definitions.

    int  main (int argc, char *argv[])
        char  *message ;
        int  moreInput ;
        TcpEndpoint  connection ;
        XnetStream  stream ;
                                         -- Connect to control server.
        tcpCall ("sony1@triplex", -1.0, -1.0, &connection) ;
        xnetCreate (connection, NULL, &stream) ;
                                         -- Send tape command.
        xnetWrite (stream, -1.0, "$tapeDrive rewind") ;
                                         -- Read status.
        xnetRead (stream, -1.0, &message, &moreInput) ;
        printf ("Completion status = %s\n", message) ;

        xnetDestroy (stream) ;    	-- Close connection.


C and C++ versions of the Xnet functions are available. The file descriptor for the socket connection underlying an Xnet stream can be retrieved for use by GUIs.

Implementing Tcl Tape Commands

Adding application-specific commands to Tcl is very easy. First, you need to decide upon a set of commands. Some example tape commands might look as follows:

    set tape [openDrive sony1]
    $tape Position endOfTape
    $tape Enable writing

The openDrive command opens the first Sony drive and returns a handle for it that is stored in variable, tape. The openDrive command also registers the handle as a dynamic Tcl command; when the handle appears as a command keyword (e.g., by dereferencing the tape variable with a $ sign), the new Tcl command is executed. For example, the $tape Position and $tape Enable commands are the same command ($tape) with different arguments, Position and Enable.

When the Tcl interpreter encounters an application-specific command, it parses the command arguments and passes them in an argc/argv array of character strings to the C function that implements the command. We have an option-scanning package that makes it a breeze to process the command arguments. (This is the same package that would be used by the tape library for scanning the open and close options.)

The tape command could perform the desired operation either by running the appropriate Triplex program or by making the actual ioctl(2) calls. The command would then return status to the client who issued the command.

Tcl procedures ("subroutine scripts") would allow the packaging of arbitrary sequences of primitive tape operations. An object-oriented extension to Tcl, [incr Tcl], provides even higher-level abstractions. In fact, by running the Triplex programs using Tcl's exec command, the TRS tape commands could be implemented entirely in Tcl - no application-specific C coding would be necessary.

Tcl-based GUIs

Stan mentioned that he had mentioned Tcl and Tk to you. The attached description of the MEDS Operator Interface, moi, will give you some idea of what can be accomplished in a Tcl-based GUI. Tk is an X Windows toolkit like the Xt-based Motif, but Tk is much easier to use, looks as good if not better, and is cheaper than Motif - Tk is free and well-supported!

Tk is not the only Tcl-based GUI, however; there are several Tcl bindings to Motif itself available. I used one of these bindings, tclMotif, to convert moi to Motif. This turned out to be much easier than expected since most of my Tk-specific windowing commands were encapsulated in [incr Tcl] object classes. By simply re-implementing these classes using Motif commands, I was able to reuse most of the existing display page definitions (e.g., the menus, the subsystem status pages, etc.). The Motif pages look nearly identical to their Tk counterparts.

What are the advantages of a Tcl-based GUI?

Tcl is obviously the greatest thing since sliced bread, so what are you waiting for?

Alex Measday  /  E-mail