@comment -*- Mode:Text; Package:TAPE; Base:10 -*- @library(patbo) @library(lisp) @comment Documentation for tape software @comment Started by DG 9/24/85 @begin(document) @parindent 0in @parskip 15pt @c baselineskip 13pt @baselineskip 18pt @textbodyindent = 0.5in @setchapterstyle open @defindex fn @synindex vr fn @synindex fl fn @synindex op fn @synindex iv fn @synindex kw fn @defindex cp @unnumbered Design of the New Tape System Since the previous implementation of tape software on the Lambda has undergone several years of use and criticism, it has been completely redesigned. The new implementation solves various problems inherent in the previous design of the tape software and provides a substantial improvement in speed, extensibility and functionality. The basic goal of the new design was user-extensibility. The ability to add support for an arbitrary tape format on any supported tape device with a minimal amount of work has been accomplished by separating the formatting from the data transfer functions into modular parts with a strictly defined interface. The result is two distinct object flavors: @l(basic-tape-format) and @l(basic-tape-device). Each has a set of required methods with specified return values used to effect operations. There are several beneficial side effects which stem from this design: @table 3 @item Multi-unit operations Control locking of the interface hardware for tape devices has been implemented at the device object level. Device locking is not permanent by process, as in the previous implementation, but controlled by user programs and checked at the device-object level. Although, the software must still inherently rely on the competence of the user to guarantee the expected results, this scheme offers much more flexibility. In addition, it allows easier implementation of specialized tape operations like tape-to-tape format translation. @item User interface The strict specification of operations on tape-devices and tape-formats offers a more controlled environment for user programs that wish to use tape storage for more obscure purposes, while allowing automatic storage programs to operate more effectively and need less user assistance. @item Abstraction of tape operations As any flavor object can be created to the specifications of a tape-format or tape-device, non-tape device objects are completely interchangeable. This permits operations like file backup to non-tape devices (such as other file-systems), without the need of specialized code. @item Speed of tape devices For dual-speed devices, the device-object can judge the transport speed that should be used by the amount of data requested, which results in substantial increase in speed for file and band transfer operations. @item Disk Partition Transfer Having tape device objects directly control the transfer of disk blocks to the tape allows the fastest data transfer rates possible since the device object can optimize operations according to the characteristics of the tape hardware. @end table The first version of the new tape system should be very stable. Yet, as it is not humanly possible to conceive of every eventuality or optimization, feedback from implementors of tape-device or tape-format support under this scheme is essential for improvement of the software. Submissions of software for other standard tape formats not in this release should be sent to LMI to be considered for inclusion in a future release. Similarly, requests for assistance in the implementation of any format are welcome and should be directed to the Customer Service Hotline. @comment ************************************************************ @chapter The Generic Tape Device Support for tape devices has been designed to be very modular, complete and easy to use. Devices as flavor objects need to support a relatively small number of operations, which can be performed as efficently (or as complexly), as the device can handle, but whose interface is simple enough to accomodate a variety of higher level formatting software, providing support for various standard tape formats. This chapter outlines the operations each tape device must support along with the characteristics particular to each operation to ensure the complete modularity of tape devices. @defflavor basic-tape-device This is the base flavor upon which all tape devices should be built. It defines no methods or instance variables, it simply @i[requires] the necessary methods and instance variables for the definition of the device. Tape devices expected to be used with the general tape software, @b(must) be built on this flavor, as it is used as the type specifier by routines in the general tape software to check the validity of tape-device objects. It is defined as an @l(:abstract-flavor). @end defflavor The values of the following instance variables should be @i[gettable] and @i[settable]. The latter should only be used within the object's method definitions, which is assumed to be accurate with respect to the limitations of the parameters. All changes of the parameters from an external source should be made through the @l(:set-options) method explained below. @defmetaivar tape-devices unit The current unit selected by the device object. @end defmetaivar @defmetaivar tape-devices density The selected density of the drive. @end defmetaivar These methods provide the interface to the device as specified: @defmetamethod tape-devices :initialize &rest init-options This method is responsible for setting up the device before any of the supported operations can be performed. The initial values of device parameters may be supplied in @ii[options]. @end defmetamethod @defmetamethod tape-devices :deinitialize &rest init-options This method is should be invoked before the device is discarded, taking care of any cleanup activities necessary (including unlocking the device if it is currently locked). @end defmetamethod @defmetamethod tape-devices :lock-device This is method should lock the device so that no other processes or processors can use it when locked. The locking scheme used and its implementation is completely up to the implementor. All that is required is that no other object/process can use the physical device after this operation has been executed, until a @l(:unlock-device) operation is executed and terminates. @b[See the section on Device Locking for a discussion on this topic.] @end defmetamethod @defmetamethod tape-devices :unlock-device This method undoes the action of the @l[:lock-device] operation. @end defmetamethod @defmetamethod tape-devices :device-locked-p This should return @l[t] if the device is currently locked for this object, or @l[nil] if not. @end defmetamethod @defmetamethod tape-devices :set-options &rest options-and-args @ii[options-and-args] should be of the form: @l[(@ii"option1 arg1 option2" ...)]. This should set each of the options to its corresponding argument, checking the validity of the arguments beforehand. If an incorrect option is specified, an error should be signalled. The return value is @l[t] if the options were correctly set. If no options are specified, this method may, at the implementor's wish, pop-up a menu for the device options to change, or otherwise query the user. @end defmetamethod @defmetamethod tape-devices :reset This operation should reset the physical device associated with the flavor object. @end defmetamethod @defmetamethod tape-devices :status This should return a list of status descriptors which indicate the state of the device. Each descriptor can be a keyword which implies logical truth of the condition or a list whose car is the keyword and cdr is a list of information about the condition. The supported status descriptors are as follows: @lisp :write-protected :busy :off-line :on-line :physical-end-of-tape :load-point :end-of-file (:error . condition-object) @end lisp @end defmetamethod @defmetamethod tape-devices :speed-threshold Since many tape drives have two transport speeds, and the reposition time plays an important factor in the overall performance of the read and write operations, this method has been provided to allow optimization of certain operations by specifying the threshold (in bytes) above which high speed can be used. The operations that currently allow speed specification are the spacing operations and search filemark operations this optimization is @l[:search-filemark] and @l[:search-filemark-reverse]. @end defmetamethod @defmetamethod tape-devices :rewind &optional (wait-p t) This should rewind the tape to BOT. If @ii[wait-p] is non-@l[nil], the method will wait for the tape to reach its load point, then return, otherwise it will return immediately. The return value should be ignored. @end defmetamethod @defmetamethod tape-devices :unload This unloads the tape and/or puts the device @l[:off-line], depending on the characteristics of the physical tape drive. This method should return immediately, if possible (not waiting for the tape to unload completely. @end defmetamethod @defmetamethod tape-devices :speed-threshold record-size This should return an integer in 8-bit bytes that determines the threshold after which @l[:high] speed should be used for spacing operations. This can return any integer if the speed optimization is meaningless for a particular device. @end defmetamethod @defmetamethod tape-devices :space number-of-records &optional (speed :low) This should move the tape forward the specified number of records. This operation will space over a filemark on the tape, counting it as a record. The @ii[speed] argument allows the user to specify how fast the drive spaces over records for drives that are dual speed. Valid values are @l[:high] or @l[:low]. This allows faster searching of the filemark when it is expected to be far from the current tape position, but the @l[:low] speed increses efficency for short files, as tape reposition time increases with transport speed. @end defmetamethod @defmetamethod tape-devices :space-reverse number-of-records &optional (speed :low) This is the same as space but moves in the reverse direction. @end defmetamethod @defmetamethod tape-devices :search-filemark number-of-sequential-filemarks &optional (speed :low) This should move forward until the specified number of sequential filemarks have been reached. The tape should be positioned after the last of the filemarks found. Eventually, if the filemarks are not found, a @l[physical-end-of-tape] error will be signalled. The @ii[:speed] argument is like for :Space. @end defmetamethod @defmetamethod tape-devices :search-filemark-reverse number-of-sequential-filemarks &optional (speed :low) This is just like @l[:search-filemark] but in reverse. @end defmetamethod @defmetamethod tape-devices :optimal-chunk-size record-size This should return the optimal amount of data (in bytes) for read/write array operations for the specified record-size. It must be some multiple of @ii[record-size]. @end defmetamethod @defmetamethod tape-devices :read-block dma-buffer record-size This should read one record from the tape into @ii[dma-buffer]. The number of bytes expected to be in the record on tape is specified as @ii[record-size]. The return value is the actual number of bytes that were in the record on tape. If this is larger than the specified record size, the dma-buffer will have only been filled up to the requested record size. If it is smaller, the dma-buffer will have only been filled up to the number of bytes in the record on tape. As no error is signalled in either case, the requestor is expected to check the return value against the expected record-size. In general, if the user does not know what the size of the next record will be, a large buffer can be used. Although the overhead increases slightly with a larger block, this is a perfectly safe thing to do. In most cases, the larges block size that can be used is 64k bytes (sometimes less). @end defmetamethod @defmetamethod tape-devices :write-block dma-buffer record-size This should write one record, @ii[record-size] bytes long, of data from @ii[dma-buffer] on the tape. @end defmetamethod @defmetamethod tape-devices :read-array array number-of-records record-size This should read the specified number of record-size records into @ii[array] from tape. This method should be able to handle the following array types: @l[art-8b], @l[art-16b], and @l[art-string]. Record-size must be an even multiple of 1024. The return value should be ignored. @end defmetamethod @defmetamethod tape-devices :write-array array number-of-records record-size This is just like @l[:read-array] only it writes from the array to tape. @end defmetamethod @defmetamethod tape-devices :read-to-disk disk-unit starting-address number-of-blocks record-size &key silent This should transfer the specified number of disk blocks from the tape to the disk starting at @ii[starting-address]. Care must be used in checking the arguments, as a reference to a non-existent disk address on the Lambda will make the machine crash. @ii[Record-size] must be an even multiple of 1024. The return values are the number of blocks actually written on disk and an error condition or NIL as in :read-array. @l[disk-unit] should be a normal disk unit spec (i.e. local disk unit number or a string " "). @end defmetamethod @defmetamethod tape-devices :write-from-disk disk-unit starting-address number-of-blocks record-size &key silent This is the similar to @l[:read-to-disk] except the direction of data transfer is reversed. @end defmetamethod @defmetamethod tape-devices :write-filemark &optional (number-of-filemarks 1) Instructs the tape device to write the specified number of filemarks on the tape. @end defmetamethod @comment ************************************************************ @chapter Tape Format Objects Tape Format objects are flavor objects which implement certain generic operations such as writing, restoring and listing files on a tape. Their responsibility is to read, examine or write data to or from the tape device which represents the correct file data (specified by the arguments) in the appropriate format. @defflavor basic-tape-format This is the base flavor upon which all tape format flavors should be built. It defines no method or instance variables, it simply @i[requires] the necessary methods and instance variables for the definition of the format. As with tape-devices, all tape formats expected to work with the general tape software must be built on this flavor. It is defined as an @l(:abstract-flavor). @end defflavor @defmetaivar tape-formats record-size This is the size in bytes for each record to be written on the tape, or @l[:variable] if this format uses variable-length records. @end defmetaivar @defmetaivar tape-formats file-stream This holds the stream object that is created if the @l[:open-file] method is invoked. This will be explained in detail below. @end defmetaivar @defmetamethod tape-formats :initialize &rest options This is similar to the operation of the same name on tape devices. It is responsible for setting up the tape format object. @ii[options] is passed to the @l[:set-options] method. @end defmetamethod @defmetamethod tape-formats :set-options &rest options-and-args As for tape devices, this is responsible for checking and setting parameters for the tape format. If no options are specified, the user should be presented with options to change by means of a pop-up window or something. @end defmetamethod @defmetamethod tape-formats :read-tape-header tape-device This should return tape header information in the form of a disembodied property list. The car of the list should be the flavor symbol of the format (i.e. @t[LMFL] format), the cdr an alternating list of properties and values. @end defmetamethod @defmetamethod tape-formats :write-tape-header plist device This should take @ii[plist] and write a proper header according to the specification of the format on @ii[device]. For safety, it should send the device a @l(:rewind) message first. @end defmetamethod @defmetamethod tape-devices :tape-is-your-format-p device This should check the tape and return @l[t] if the tape is of this format, assuming that the tape is already rewound, NIL otherwise. @end defmetamethod @defmetamethod tape-formats :restore-file device &key transform query (overwrite :always) (create-directory :always) silent Restore a file from the tape. @table 3 @kitem :transform If this is a pathname or a string, the components of the pathname of the file on tape are merged into this one. If it is a function, it must take arguments: (in internal lisp machine format) @lisp (device directory name type version) @end lisp and return a pathname to which the file will be restored. @kitem :query If non-@l[nil], the user will be asked for each file whether to restore it. @kitem :overwrite Decides whether to overwrite an existing non-deleted file with the same pathname (including version). Valid values are: @l(:always :query :never). @kitem :create-directory Decides whether to create a directory for a file to be restored if the directory does not exist. Valid values are: @l(:always :query :never :error). @l[:never] skips over the file, @l[:error] will signal a directory-not-found error. @kitem :silent If non-nil, should not print anything unless a query is in order. Otherwise, this method should print out what file the tape file is being restored to. @end table @end defmetamethod @defmetamethod tape-formats :write-file device file &key (end-of-tape-action :continue) silent Writes a file on the tape. @l[device] and @l[silent] are as usual. @table 3 @item file This should be a string, pathname or a file property list in the form @l[(@ii"truename" . (@ii"prop value" ...))] as returned by @l[fs:directory-list]. If the argument is a file plist, then the properties in the plist are written to tape, otherwise the file properties are derived from the input stream at write time. @item end-of-tape-action What happens when the end of tape is reached during this operation is dependent on this variable. @table 3 @kitem :continue This directs the format software to continue to another tape according to the specifications of the format. This may, though, be an error in some cases, since some formats don't know about multi-tape save-sets. @kitem :error This means that an error should be signalled according to when the filemark was encountered. The flavor to signal is @l[end-of-tape-writing-header] or @l[end-of-tape-writing-file] depending on when the end of tape was encountered. These error flavors are documented elsewhere in this manual. @kitem :return This should cause an appropriate error condition to be returned immediately. (See above). @end table @end table @end defmetamethod @defmetamethod tape-formats :write-partition partition device disk-unit &key silent number-of-blocks start Writes a partition to tape. @l[:device] and @l[:silent] are as usual. @table 3 @kitem :partition This should be a complete partition name as a string (i.e. "LOD1") @kitem :disk-unit This should be a disk unit argument like those passed the general system disk software. To specify a local disk unit, provide an integer. To specify a disk on a remote host, provide a string that looks like " ". Providing a string form for the local host will still use the remote disk server. @kitem :whole-thing If this is T, then the whole partition is copied; if it is a number, then that number of blocks is copied; if it is NIL, then only the active blocks in cases of compressed format bands will be copied. @item :offset If this is provided, it must be an integer representing the offset into the partition to start copying from. @end table @end defmetamethod @defmetamethod tape-formats :compare-file device &key transform silent (error-action :return) Compares the next file on tape with the source it was dumped from. Transform is treated exactly as for :restore-file, and should provide the pathname of the file to be compared against. If this argument is NIL, then the local host is assumed to be the source. If silent is nil, then this method should print out messages concerning the comparison of the files. If the file compares successfully, then the plist of the file should be returned. If the file gets a compare error, @l[error-action] determines the action to take: @table 3 @kitem :return Returns an error condition instance of the appropriate error flavor: @l[compare-error], @l[source-not-found], @l[source-file-changed]. @kitem :error Signals an appropriate error condition. @end table @end defmetamethod @defmetamethod tape-formats :beginning-of-file device This positions the tape to the beginning of the current file. Return value should be ignored. Warning: Be sure that repeated invocations of this method do not space to the previous file. @end defmetamethod @defmetamethod tape-formats :next-file device &optional (number-of-files 1) Positions the tape at the beginning of the file that is @i(number-of-files) away from the current file (i.e. 1 specifies the next file). @end defmetamethod @defmetamethod tape-formats :previous-file number-of-files device Like @l[:next-file] but moves backwards. @end defmetamethod @defmetamethod tape-formats :find-file device match This operations searches for file on tape. @ii[match] can be of the following types: @description @item list Car should a symbol, either @l[or] or @l[and], cdr should be a list of valid match arguments. @l[tape-file-match] is called on all of elements with the same plist, and the values applied to @l[and] or @l[or] appropriately to determine the return value. @item string or pathname Uses @l[:pathname-match] operation on @ii[match] pathname. @item function, closure, or symbol Funcall @ii[match] with plist as the argument. @end description If the processing of the match argument returns non-@l[nil], then the tape is positioned at the beginning of the matched file, and the file's plist returned. Otherwise the search continues. @end defmetamethod @defmetamethod tape-format :find-file-reverse match device This is like @l[:find-file] but moves backwards. If the beginning of the tape is reached before a match is found, a @l[physical-beginning-of-tape] error should be signalled. @end defmetamethod @defmetamethod tape-formats :open-file device &key (:direction :input) (:byte-size :default) (:characters :default) plist This function returns a stream according to the arguments which have the same meaning as for @l[open]. @ii[plist] is only meaningful for @l[:output] streams, and must be supplied in that case. The file's properties are copied onto the si:property-list instance variable of the stream, allowing the use of the generic property list functions (get, putprop, plist, etc.). The stream returned is basically exatcly like that returned by @l[FS:MAKE-MT-FILE-STEAM] in the old tape software. @end defmetamethod @defmetamethod tape-formats :list-files device &key (stream *standard-output*) (number-of-files -1) Should print a description of each file on the tape to @l(stream). The listing should stop after @ii[number-of-files] is reached or the end of tape is encountered, returning a list of the file property lists if the files found. If @l[:stream] is NIL, then nothing should be printed. @end defmetamethod @defmetamethod tape-formats :finish-tape device Marks the logical end of tape on @l(device). For convenience, the tape should be re-adjusted so that any further write operations will not be after the logical end of tape. This operation simply should guarentee that the logical end of tape is represented on the tape. @end defmetamethod @defmetamethod tape-formats :rewind device &optional (wait-p t) This should cause the tape on @ii[device] to be rewound. It has the same meaning as for tape-devices, but is provided here since some format objects may need to update some internal information when the tape is rewound. @end defmetamethod @defmetamethod tape-formats :unload device This should cause the tape on the device specified to be unloaded. This should take the same care of saving the state of the tape format object as the @l[:rewind] method. @end defmetamethod @defmetamethod tape-formats :position-to-append device Position tape so that all subsequent @l[:write-file] operations will add the files to the end of tape. @end defmetamethod @comment ************************************************************ @chapter Error Handling The new implementation of the tape software has gone quite out of its way to provide an accurate and consistent system of error condition flavors, to allow reliable catching and handling of various tape errors and states. The following set of flavors should be used in all places where they logically fit. Higher level software will depend on this consistency and will be able to provide more `intelligence' to tape operations rather than dropping through to the error handler at every exception. Errors are subclassified to allow easier intuitive understanding of the condition and also to allow more intelligent user interfaces and automated programs to operate more reliably. Each classification flavor (with the exception of @l[hardware-error] and @l[driver-error]) is defined as an @l(:abstract-flavor) (see the Lisp Machine Manual [flavors]). This is the base flavor for all tape-related errors; all other error flavors use this one. @defflavor tape-error Abstract flavor for the classification of all tape errors, built on @l[error]. @end defflavor @comment ****************************** @section Hardware Errors These errors are internal hardware errors that cannot be reasonably handled by other software (fatal hardware errors). Use this for building flavors internal to the drivers for specific devices. It is acceptable to allow these conditions to be passed through to the error handler in the case of a fatal hardware error. @defflavor hardware-error @l[:device-type], @l[:error-code], and @l[:error-message] are required instance variables. The @l[:device-type] should be a symbol an is primarily for the user to identify the device that has errored if the debugger has been entered. The @l[:error-code] driver dependent. The @l[:error-message] should be a string which is used to report the error if the debugger is entered. @end defflavor @comment ****************************** @section Driver Errors Driver errors are internal errors in the driver software. These should be used within the driver software for signalling conditions @i[only] within the driver level. All exceptions that need to be signalled to higher level software, should be converted into a condition of an appropriate flavor (listed below), rather than signalling the internal error condition. Therefore, conventionally, if the debugger is entered because of a @l[driver-error], it should be considered a bug in the driver software and should be reported to the implementor(s) of the driver. @defflavor driver-error @l[:device-type], @l[:error-code], and @l[:error-message] are required instance variables. @end defflavor @comment ****************************** @section Device Errors Device errors are typical, sometimes expected, errors that the device may encounter, such as the physical end of the tape, device not ready, etc. The following is the base, uninstantiable flavor upon which all other @l[device-error] flavors depend. @defflavor device-error Abstrace flavor for classification of device errors. @end defflavor These are the currently defined device error flavors: @defflavor device-unavailable This error should be signalled when the device is being used by another processor or another process within the same processor. @l[:device-type] should be a symbol describing the device (i.e. 'tapemaster). @l[:current-owner] should be either an integer or a cons (not a list!). If it is an integer, than it is the NuBus slot number of the processor currently `owning' the device hardware interface. If it is a list, the car of the cons is the device that is currently using the device, the cdr is the process in which the device object is being accessed. The process may not be significant for some locking schemes, and useful in others. The @s[proceed-types] defined for this condition are: @l[:steal-device-internally], @l[:steal-device-from-other-processor], @l[:wait-for-device-free]. @end defflavor @defflavor wait-timeout This error should be used for all unrecoverable timeout conditions. @l[:device-type], @l[:unit], @l[:seconds-waited], and @l[:wait-string] are required instance variables for this flavor. @l[:wait-string] should describe the timeout. @end defflavor @defflavor bad-tape This error should be signalled if there is an indication that there is a defect in the tape. @l[:device-type] and @l[:unit] are required instance variable. @end defflavor @defflavor blank-tape Should be signalled if an attempt to read the tape is made and it is detected as blank by the device. @l[:device-type] and @l[:unit] is the only required instance variable. @end defflavor @defflavor physical-end-of-tape When the physical end of the tape is detected, this error should be signalled. @l[:device-type] is as usual. @l[:unit] should be the unit number for the device @l[:data-transferred] should be is a signaller dependent value that represents how much of the operation (read/write/space) was carried out before the end of tape was reached. For more detailed information about this, see the documentation for the read and write operations for @l[basic-tape-device]. It is important not to confuse this with @l[logical-end-of-tape] explained below. @end defflavor @defflavor physical-beginning-of-tape This is exactly like @l[physical-end-of-tape] except it is for reverse direction operations (currently only spacing operations). This should NOT be signalled by rewind operations, since the beginning of the tape is expected. @l[:device-type], @l[:unit], and @l[:data-transferred] are as for the aforementioned flavor. @end defflavor @defflavor filemark-encountered This should be signalled when a hard filemark on the tape is encountered during a read operation. @l[:device-type], @l[:unit], and @l[:data-transferred] are required instance variables. @end defflavor @comment ****************************** @section Format Errors Format errors are expected conditions (like @l[logical-end-of-tape]) or errors in the format of information on the tape with respect to the specific format standard (a bad file headers, for instance). @defflavor format-error Abstract flavor for the classification of format errors. @end defflavor @defflavor bad-tape-header This should be signalled when the tape header (as specified by the format) is invalid in some way. This is in most cases a fatal error. @l[header] is a string provided for debugging so the user can examine it and possibly determine how corrupted the header is. @l[format-type] is provided identify the format of the tape. @end defflavor @defflavor bad-file-header This should be signalled when there is an indication that a file header on the tape is invalid. This is usually fatal error, but unfortunately in some cases has to be used to determine the logical end of tape. @l[:format-type], and @l[:header] are the required instance variables, as in @l[bad-tape-header]. @end defflavor @defflavor logical-end-of-tape This indicates the end of the tape, in file terms. Whether there are more files on the tape is dependent on the format. The format software for each format should be careful to correctly handle cases of repeated attempts to access any more files, if there aren't any more. @l[:device-object] is the only required instance variable and should hold the device object the format detected the logical end of tape on. @end defflavor @defflavor end-of-tape-writing-header This condition is used if a @l[physical-end-of-tape] error was signalled by a device while the formatting software was trying to read a file header. This might not always be signalled, since the user may opt to have the format handle the end of tape internally. (See the @l[:write-file] operation for tape formats for more information.) @l[:file-plist] is the only required instance variable and should hold the property list of the file that was being written. @l[:device] is the object which signalled the physical end of tape. @end defflavor @defflavor end-of-tape-reading-header This is just like @l[end-of-tape-reading-header], but signalled during a file read (or compare) operation. @l[:device] is the only required instance variable and should hold the device object which signalled the end of tape. @end defflavor @defflavor end-of-tape-writing-file This indicates that the physical end of tape was encountered while writing the file's data on the tape. @l[:file-plist] and @l[:device] are as in @l[end-of-tape-writing-header]. @l[bytes-transferred] indicates how many bytes of the file were transferred before the end of the tape was encountered. Note carefully that @l[bytes-transferred] corresponds to the @i[BYTE-SIZE] of the file, which may vary but is typically 8 or 16 bits. @end defflavor @defflavor end-of-tape-reading-file This is just like @l[end-of-tape-writing-file] but for read or compare operations. @l[:file-plist], @l[:device], and @l[:bytes-transferred] are the required instance variables. @end defflavor @defflavor compare-error Indicates that there was an error comparing a tape file and its source. @l[:source-file] is the pathname of the source file used to compare, @l[:file-plist] is the property list of the file compared. @end defflavor @defflavor compare-source-not-found Indicates that the source for the file to be compared was not found. @l[:source-file] is the file it tried to find. @end defflavor @defflavor compare-source-changed Indicates that the attributes of the source file changed in some way since the file was written to tape. @l[:source-plist] is a plist of the source file's properties, @l[:file-plist] is that of the file on tape. @end defflavor @comment ****************************** @section User Errors User errors are errors that the user can correct and retry, or that the user has precipitated by not following the conventions (not mounting the tape, for instance). @defflavor user-error Abstract flavor for the classification of user errors. @end defflavor @defflavor write-protected This should only be signalled by operations that wish to alter the data on the tape. It obviously indicates that the tape in the driver is write protected. @l[:device-type], and @l[:unit] are required instance variables that give the appropriate information as to which drive (if there are more than one) needs attention. @end defflavor @defflavor tape-not-ready This usually means that the tape driver is not @s[online] or the tape is not mounted. @l[:device-type], and @l[:unit] are the required instance variables. @end defflavor @defflavor unknown-format This indicates that the tape is of a format unknown to the software. This should is signalled by higher level software that checks the tape against all the supported tape formats (using :tape-is-your-format-p) and fails to find appropriate format support. @l[:device], @l[:unit], are as usual. @l[:header-string] is provided for debugging. @end defflavor @defflavor file-stream-exists This indicates that a file stream already exists for this particular format object. It should be signalled by the @l[:open-file] method for tape formats. For a discussion of why only one stream may be open at a time, see the documentation of the @l[:open-file] method for tape formats. Fixing this condition, by closing the existing stream, may not always work as desired, depending on the intelligence of the format software. And since programs that use the open file feature should use @l[WITH-OPEN-STREAM], this error condition should be considered fatal and due to some user mistake, or an internal error in the format software. @l[:format-object] holds the format object in which the error occurred. @l[:file-stream] is the stream that exists, which is provided for closing. (The file stream is also a `gettable' instance variable of format object.) @end defflavor @defflavor no-such-partition This error is signalled when the user asks to operate on a partition that doesn't exist. This should be a general system error, but for not will be implemented locally here. @l[:partition] is the name of the partition requested. @l[:disk-unit] is the drive-number of the disk. @l[:host] is the machine whose disk we are talking about. @end defflavor @defflavor invalid-option This should be signalled by the @l[:set-options] methods for format and device objects (there is no need for a distinction here). @l[:option] is the invalid option that was supplied, @l[value] is its corresponding value. @l[:object] is the object which rejected the option. @end defflavor @defflavor write-in-middle-of-tape This may be signalled by the formatting software if it is generally unacceptable to start writing data if not in the middle of the tape. (For example: aborting out of a @l[:list-files] operation and then using @l[:write-file] without rewinding first.) This adds an extra level of protection against lossage due to carelessness, but is by no means required by the format software. @l[:device-object] is the only required instance variable. @end defflavor @defflavor read-during-write This is similar to @l[write-in-middle-of-tape] but indicated that attempt was made to read data on the tape before the end of tape was written. Again, in some cases with some devices, this is an acceptable thing to do, but in others might simply confuse things and cause the user to re-write the tape. @l[:device-object] is the only required instance variable. @end defflavor @defflavor not-supported This can be used when support for a particular format or device is being written. Since the software requires that all documented operations on a device be provided before the object can be used, one can use this to signal an error for operations that have not yet been implemented. Its intended use is for non-distributed or special user implemented format or device support, where it is allowable to have unsupported operations. @l[:device-object] is the object which errored, and @l[:operation] is the operation in question. @end defflavor @defflavor protocol-violation This indicates that an argument passed by the user or by software did not adhere to the specifications set out by this document. It is the type of error condition that is signalled when you pass an @l[ART-Q] array as the @s[array] argument to the @l[:write-array] operation for tape devices. @l[:format-string] is the only required instance variable. @l[:format-args] is accepted and defaults to @l[NIL]. @end defflavor @comment ************************************************** @section Higher Level Software Errors For the purpose of classification without exception, the following flavor is defined. It is expected that all layers between but not including the format support and user-interface levels build their error flavors on this flavor. It is not clear exactly how useful this will be in the long run, but for purposes of extensibility it will be included. @defflavor higher-level-software-error Abstract flavor for higher level tape software to build error flavors upon. @end defflavor @summarycontents @contents @end(document)