#ifndef _NSRSSVOL_ //-*-c++-*-
#define _NSRSSVOL_

//----------------------------------------------------------------------
//nsrSSVol.h Single-Surface Volume Classes
//
//   Many of these objects may be enhanced to use in multiple-surface
//   volumes, but they are all currently used by the
//   SingleSurfaceVolume class.
//
//      Unpublished Confidential Information of Hewlett-Packard
//      Company. Do not disclose.  Copyright (c) Hewlett-Packard
//      Company 1995. All rights reserved
// 
// The contents of this software are proprietary and confidential to
// the Hewlett- Packard Company, and are limited in distribution to
// those with a direct need to know.  Individuals having access to
// this software are responsible for maintaining the confidentiality
// of the content and for keeping the software secure when not in use.
// Transfer to any party is strictly forbidden other than as expressly
// permitted in writing by Hewlett-Packard Company.  Unauthorized
// transfer to or possession by any unauthorized party may be a
// criminal offense.
//
//                  RESTRICTED RIGHTS LEGEND
//
//      Use,  duplication,  or disclosure by the U. S. Government is
//      subject to restrictions as set forth in subparagraph (c) (1)
//      (ii) in the Rights in Technical Data and Computer Software
//      clause in DFARS 252.227-7013 or any other successor clause.
//
//                      HEWLETT-PACKARD COMPANY
//                      3000 Hanover St.
//                      Palo Alto, CA  94304 U.S.A.
//
//      Rights for non-DOD U.S. Government Departments and Agencies
//      are as set forth in FAR 52.227-19 (c) (1,2) or any other
//      successor clause.
//
//  CLASSES:
//   (Structural Abstractions)
//     PhysicalVolumeSet
//     FileSet
//     LogicalVolume
//     Partition
//     PhysicalVolume
//     Integrity              (!!! not implemented yet)
//     UnallocatedVolumeSpace (!!! not implemented yet)
//   (Sequence Abstractions)
//     VolDescSequence        (!!! inside of SSVol)
//     IntegritySequence      (!!! not implemented yet)
//     FileSetDescSequence    (!!! inside of SSVol)
//   (Compound Abstractions)
//     SingleSurfaceVolume
//
//  NOTES:
//
//  BASIC OVERVIEW:
//
//   Structural Abstractions
//   
//   The Structural Abstractions are simple representations of the
//   on-disk ISO/UDF structures - They hold all of the information
//   in their associated on-disk structure, and they all are
//   associated with a single on-disk structure. There is a one-to-one
//   correspondence between these objects and on-disk
//   structures. These may be viewed as the same as the on-disk
//   structures with which they are associated, except that
//   logically-related Abstractions point to each other.
//
//   They are all woven into a "web" which reflects their logical
//   relationships to each other. Thus, since each Partition is
//   associated with a LogicalVolume, it contains a pointer to its
//   associated LogicalVolume, and vise versa.
//
//   This architecture is intended to enable full support of WORM and
//   multi-volume sets without having to restart at ground zero. Thus,
//   the PhysicalVolumeSet object is defined, and a pointer to it is
//   reserved in the PhysicalVolume structure, even though it is not
//   implemented yet. Also, LogicalVolumes may ultimately be
//   associated with multiple Partitions, so the LogicalVolume object
//   supports methods to translate between PartitionReferenceNumber
//   and partition pointer.
//
//   In addition to the objects being basic abstractions of on-disk
//   structures, the Partition and PhysicalVolume objects also support
//   drive operations (e.g., read(), write(), etc.). This is because
//   they are also abstractions of storage space - space inside of a
//   partition and space on a PhysicalVolume, respectively.
//
//   Sequence Abstractions
//   
//   The Sequence Abstractions understand the reading and writing of
//   the different sequences. Their job is to initialize their
//   associated Structural Abstraction(s) from the on-disk structures,
//   and make sure they are all tied together appropriately.
//
//   This architecture is intended to enable extension of
//   functionality into WORM support with minimal rewriting. For
//   example, WORM allows a sequence of multiple FileSets in a
//   FileSetDescSequence, but Rewritable does not. Thus, this
//   sequence object should be the focal point for the WORM
//   multiple-fileset support implementation.
//   
//   Compound Abstractions
//   
//   The Compound Abstraction(s) uses the Sequence Abstractions to
//   ultimately tie together ALL Structural Abstractions, and it
//   provides a single point of contact for most users. Thus, its
//   principle function is to weave the entire web from the disk, and
//   to provide access to any and all information contained in the
//   on-disk structures..
//
//  CURRENT IMPLEMENTATION
//
//   General
//
//   In general, NONE of the objects currently support any of the
//   following:
//
//     WORM
//     Writing
//     Multiple Surfaces
//
//   Architecture
//
//   Currently, the Sequence Abstractions are absorbed into the
//   Compountd Abstraction of the SingleSurfaceVolume. The
//   SingleSurfaceVolume still maintains the single point of contact
//   for the other structures.
//
//   Structural Abstractions
//  
//   These have been kept extremely basic. Where
//   multiple-volume-set-supporting versions would contain tables of
//   pointers to other objects (e.g., the LV should contain a table of
//   partition pointers), the current versions tend to support a
//   single pointer. The interfaces have been defined in anticipation
//   of this ultimate support, but may still require changes when
//   multiple-volume set support is implemented.
//
//   In addition, if information is not already needed by a user of
//   the object(s), it is not yet implemented or even necessarily
//   defined.
//
//   Sequence Abstractions
//   
//   VolDescSequence
//     This currently supports only the situations expected on single
//     surface volumes - e.g., a single Partion, a single
//     LogicalVolume, etc. It may not ensure that the prevailing
//     instance of a given descriptor is found either. This will be
//     REQUIRED for WORM support, but is likely not needed on
//     Rewritable media, since the other major implementor of this
//     standard, Micro Design International, does not write disks in
//     this way.
//   IntegritySequence
//     This only supports the Rewritable constraints of a single
//     LogicalVolumeIntegrityDesc being recorded in the Integrity
//     Sequence Extent.
//     This is entirely unimiplemented.
//   FileSetDescSequence
//     This currently only supports extracting a single file set from
//     the sequence. This is all that UDF requires unless on WORM, so
//     this will only be extended as part of WORM support.
//   
//   Compound Abstractions
//
//   The SingleSurfaceVolume object effectively hides the web of other
//   objects from its users, but also allows access to those more
//   publicly exposed, such as the Partition, LogicalVolume, and
//   PhysicalVolume. In addition, it coordinates the reading of all of
//   the sequences.
//
//   It supports reading a disk's structures, but does NOT support
//   writing them (yet).
//
//----------------------------------------------------------------------
// $Source: /projects/HMS/nsr/udfCore/ss/nsrSSVol.h,v $
// $Revision: 1.41 $    $Author: hmgr $
// $State: Exp $        $Locker:  $
// $Date: 96/06/27 02:56:34 $
//

//----------------------------------------------------------------------
// CLASS: PhysicalVolumeSet                --DVM
//
//  PhysicalVolumeSet objects comprise a set of PhysicalVolume
//  objects. Each one may have one or more LogicalVolume objects
//  associated with it.
//
//  PhysicalVolumeSet is currently UNIMPLEMENTED.
//
// PUBLIC METHODS:
//  None yet.
//
// USAGE NOTES:
//  Should mention constructor/lifecycle after this is defined..
// 
//----------------------------------------------------------------------
// COLLABORATORS:  
//  Points to PhysicalVolume.
//  Points to LogicalVolume.
//
// PRIVATE METHODS:
//  None yet.
//
// IMPLEMENTATION NOTES:
//
//   The process by which PhysicalVolume objects are associated with
//   this object has not been fully defined. It may be tricky, in that
//   the PhysicalVolume object, containing the PrimaryVolumeDesc, is
//   the sole holder of which PhysicalVolumeSet it is a part of. This
//   association is by VolumeSetName, as well -- i.e., it is a part of
//   a VolumeSet if it names that VolumeSet in its descriptor.
//
//   The current thought is that each time a new PhysicalVolume is to
//   be added to a set of volumes, it is checked to see that its name
//   matches the current VolumeSetName. This name may be set
//   originally from a single PhysicalVolume object, via an explicit
//   method. The Archive Object's implementation of volume sets should
//   provide an excellent example of how to form volume sets out of
//   volumes. It should likely even support explicit volume growth
//   methods, etc., mimicking the Archive object to a very detailed
//   level.
//
//   Also unresolved is the exact life cycle of this object.
//
//----------------------------------------------------------------------

class PhysicalVolumeSet {};     // Empty implementation.

class LogicalVolume;            // Forward Reference ONLY.

//----------------------------------------------------------------------
// CLASS: Integrity     --DVM
//
//  This is the abstraction associated with the Logical Volume's
//  integrity, or LogicalVolumeIntegrityDesc. It is either Open
//  (dirty) or Closed (clean).
//
// PUBLIC METHODS:
//  Integrity()
//      Constructs from a pointer to a LogicalVolume.
//  markOpen()
//      Sets the state to open (in memory).
//  isOpen()
//      Returns True if volume is open (dirty).
//  markClosed()
//      Sets the state to closed (in memory).
//  isClosed()
//      Returns True if volume is closed (clean).
//  uniqueID()
//      Sets/Gets Next available UniqueID.
//  numFiles()
//      Sets/Gets number of files on this Logical Volume.
//  numDirectories()
//      Sets/Gets number of directories on this Logical Volume.
//  toDisk()
//      Writes in-core representation to the disk.
//  fromDisk()
//      Reads in the object from the disk.
// USAGE NOTES:
//  This adheres to the fairly common paradigm of other structural
//  abstractions, in that it has separate to/fromDisk() functions,
//  with methods to set/get all relevant fields.
// 
//----------------------------------------------------------------------
// COLLABORATORS:  
//  Contains a LogicalVolumeIntegrityDesc
//  Points to a LogicalVolume
//
// PRIVATE METHODS:
//  none.
//
// IMPLEMENTATION NOTES:
//  Internal Notes go here (special cases, algorithm issues, etc.)
//
//----------------------------------------------------------------------

class Integrity {

    LogicalVolumeIntegrityDesc integrityDesc_ ;
    LogicalVolume *            logVolumep_    ;

public:

    Error checkValidity() {
        return logVolumep_->checkValidity();
    }
    // Constructor
    Integrity(LogicalVolume * lvp)
            : integrityDesc_(1),
              logVolumep_(lvp)
    {
        markOpen();
    }
    Error error() const {
        return integrityDesc_.error(); }

    // ----- Setter/Getter pairs -----

    // - Open/Closed stuff
    void markOpen(void) {
        integrityDesc_.integrityType(integ_Open);
        return;
    }
    Boolean isOpen(void) const {
        return integrityDesc_.integrityType() == integ_Open ?
            True : False;
    }

    void markClosed(void) {
        integrityDesc_.integrityType(integ_Closed);
        return;
    }
    Boolean isClosed(void) const {
        return integrityDesc_.integrityType() == integ_Closed ?
            True : False;
    }

    // - Other fields of the LVID
    void uniqueID( UINT64 uid ) {integrityDesc_.uniqueID = uid;}
    UINT64 uniqueID(void) const {return integrityDesc_.uniqueID;}
    
    void numFiles( UINT32 nf ) {integrityDesc_.numFiles = nf;}
    UINT32 numFiles(void) const {return integrityDesc_.numFiles;}
    
    void numDirectories( UINT32 nd ) {integrityDesc_.numDirectories = nd;}
    UINT32 numDirectories(void) const {return integrityDesc_.numDirectories;}

    // Getter methods only
    UINT32 size(void) const {return integrityDesc_.sizeTable[0];}
    UINT32 freeSpace(void) const {return integrityDesc_.freeSpaceTable[0];}

    // ISO methods
    void toDisk( Error & err ) ;
    void fromDisk( Error & err ) ;
};

//----------------------------------------------------------------------
// CLASS: FileSet     --DVM
//
//  This is the abstraction associated with a FileSetDescriptor,
//  holding the location of the ICB for the root directory, as well as
//  the name of the file set..
//
// PUBLIC METHODS:
//  FileSet()
//      constructs from a pointer to a LogicalVolume.
//  checkValidity()
//      Returns an Error if not OK or if any objects upon which it
//      depends is not OK.
//  error()
//      Returns any error associated with its state.
//  fromISO()
//      Fills in its state information from on-disk FileSetDesc.
//  rootICBAddr()
//      Returns the LogExtent for the Root ICB for this FileSet.
//
// USAGE NOTES:
//  User notes go here.
// 
//----------------------------------------------------------------------
// COLLABORATORS:  
//  Contains a FileSetDesc.
//  Points to a LogicalVolume.
//
// PRIVATE METHODS:
//  None yet.
//
// IMPLEMENTATION NOTES:
//  Needs to be supplemented with a name() method.
//
//----------------------------------------------------------------------

class FileSet {

    FileSetDesc     fileSetDesc_ ;
    LogicalVolume * logVolumep_  ;

  public:

    Error checkValidity() {
        return logVolumep_->checkValidity();
    }
    // Constructor
    FileSet(LogicalVolume * lvp)
            : logVolumep_(lvp) {}
    Error error() const {
        return fileSetDesc_.error(); }

    // Getter/Setter pairs
    void fileSetID(const String & fsid) {
        fileSetDesc_.fileSetID=fsid;
    }
    String fileSetID(void) const {
        return fileSetDesc_.fileSetID;
    }
    
    LogExtent rootICBAddr(Error & err) const {
        LogExtent ricbe;
        fileSetDesc_.rootDirICB.toLogExtent(logVolumep_,ricbe,err);
        return ricbe;
    }
    void rootICBAddr(const LogExtent & ricbe,
                     Error & err) {
        fileSetDesc_.rootDirICB.fromLogExtent(ricbe,err);
    }
    
    // ISO methods
    void fromISO( const ByteArray &buf,
                  LogExtent & le,
                  Error & err ) {
        fileSetDesc_.fromISO( buf,0,le.startBlock() );
        logVolumep_ = le.logVolumep();
        err = fileSetDesc_.error();
        return;
    }
    void toISO( ByteArray &buf,
                const PhysExtent & pext,
                Error & error ) ;
};
    
class Partition;                // Forward Reference ONLY

//----------------------------------------------------------------------
// CLASS: LogicalVolume     --DVM
//
//  Abstraction of a Logical volume which is a set of partitions which
//  share a physical volume.
//
// PUBLIC METHODS:
//  LogicalVolume()
//      Constructs from a pointer to a Partition.
//  partitionp()
//      Returns a pointer to the Partition associated with the
//      supplied PartitionReferenceNumber.
//  identifier()
//      Returns the LogicalVolume Identifier.
//  integSeqExtent()
//      Returns the First PhysExtent of the Integrity Sequence.
//  partRefNo()
//      Returns the PartitionReferenceNumber associated with the
//      Partition whose pointer is passed in.
//  checkValidity()
//      Returns an Error if not OK or if any object upon which it
//      depends is not OK.
//  Error error()
//      Returns any error associated with its state.
//  fromISO()
//      Fills in its state information from on-disk FileSetDesc.
//  fsdsExtent()
//       Returns the LogExtent holding the first part of the
//       FileSetDesc sequence.
//  blockSize()
//       All blocks in an LV must be the same.
//  numBlocks()
//       This returns the total number of blocks in the LogicalVolume.
//  maxExtLen()
//       This returns the maximum allowed length of an extent in the
//       LogicalVolume.
// USAGE NOTES:
//  User notes go here.
// 
//----------------------------------------------------------------------
// COLLABORATORS:  
//  Contains a LogicalVolumeDesc.
//  Points to a Partition (multiple in future)
//  Points to a FileSet   (multiple in future)
//
// PRIVATE METHODS:
//  None yet.
//
// IMPLEMENTATION NOTES:
//  This currently holds a single partition pointer, but needs to be
//  changed to support multiple surfaces. Also holds a single FileSet
//  pointer, which needs to be changed to support multiple file sets
//  for WORM.
//
//----------------------------------------------------------------------

class LogicalVolume {

    LogicalVolumeDesc logVolDesc_     ;
    Partition       * partitionp_     ;
    FileSet         * fileSetp_       ;

  public:

    // Constructor
    LogicalVolume ( Partition * pp ) :
        logVolDesc_ (1),
        partitionp_ (pp)
    {
        if (partitionp_ != NULL)
            pp->logVolumep(this);
    }

    // Misc methods to find out about the LV.
    Partition * partitionp( UINT32 partRefNo ) const {
        return partitionp_; }
    UINT32 blockSize() const ;
    UINT32 numBlocks() const ;
    UINT32 maxExtLen( void ) const
    {
        return ExtLength::maxLength() - blockSize() + 1;
    }

    // Getter/Setter pairs
    String identifier( void ) {
        return logVolDesc_.logicalVolumeID;
    }
    void identifier( const String & id ) {
        logVolDesc_.logicalVolumeID=id;
    }

    PhysExtent integSeqExtent( Error & err ) {
        PhysicalVolume * pvp = partitionp_->physVolumep();
        PhysExtent ise(pvp,0,0);
        logVolDesc_.integritySeqExtent.toPhysExtent(pvp,ise,err);
        return ise;
    }
    void integSeqExtent(const PhysExtent & ise,
                        Error & err ) {
        logVolDesc_.integritySeqExtent.fromPhysExtent(ise,err);
    }

    LogExtent fsdsExtent(Error & err) {
        LogExtent fsdse;
        logVolDesc_.fileSetDesc.toLogExtent( this,
                                             fsdse,
                                             err );
        return fsdse;
    }
    void fsdsExtent(const LogExtent & fsde,
                    Error & err) {
        logVolDesc_.fileSetDesc.fromLogExtent(fsde,err);
    }

    // For now, only supports single surfaces -- only one partition.
    UINT32 partRefNo( Partition * partp ) const {
        return 0; }
    Error checkValidity() const {
        return partitionp_->checkValidity(); }
    Error error() const {
        return logVolDesc_.error();
    }

    // ISO methods
    void fromISO( const ByteArray &buf,
                  const PhysExtent & pe,
                  Error & error) {
        logVolDesc_.fromISO( buf,0,pe.startSector() );
        error = logVolDesc_.error();
    }
    void toISO( ByteArray &buf,
                const PhysExtent & pext,
                Error & error ) ;

};

//----------------------------------------------------------------------
// CLASS: Partition     --DVM
//
//  The Partition class is the basic abstraction associated with the
//  NSR PartitionDesc. It has its own error state, which is typically
//  set by fromISO().
// 
//  Its central data member is a PhysExtent which describes the actual
//  partition location on the disk (along with its length). This is
//  the data member which ties it to a specific PhysicalVolume object.
//  
//  It also contains LogExtents holding the locations on disk where
//  the erased and unerased SpaceResources are located. These are
//  settable from the outside, and are usually set by the SR
//  constructors and/or initialization methods.
// 
//  It is also tied to a specific LogicalVolume by a pointer. This
//  pointer is set by any LogicalVolume object which claims the
//  partition. It is NOT set at construction (unlike the
//  PhysExtent/PhysicalVolume).
// 
//  In addition, it contains a pointer to the spaceResource for the
//  partition. The SR must be separately constructed and then attached
//  to the Partition via a setter. It is afterward available through
//  the getter method. Thus, an appropriate initialization sequence
//  is:
// 
//   thePartp = new Partition(...);
//   theSR    = new MasterSpaceResource(thePartp, ...);
//   thePartp->spaceResourcep(theSR);
// 
//  The to/fromISO() methods provide all appropriate translations
//  between the in-core and on-disk images.
//
// PUBLIC METHODS:
//  Partition()
//      Constructs a Partition from a PhysicalExtent, or from a
//      PhysicalVolume pointer, a start and a number of sectors.
//  blockSize()
//      Returns the number of bytes in each block in the Partition.
//  numBlocks()
//      Returns the number of blocks in the Partition.
//  startSector() const {
//      Returns the first sector on the PhysicalVolume which is in
//      the Partition.
//  physVolumep()
//      Returns a pointer to the associated PhysicalVolume.
//  erasedSpaceTblExt()
//      Sets or gets the LogExtent holding the Erased Space Table.
//  erasedSpaceBMapExt()
//      Sets or gets the LogExtent holding the Erased Space Bitmap.
//  unerasedSpaceTblExt()
//      Sets or gets the LogExtent holding the Unerased Space Table.
//  unerasedSpaceBMapExt()
//      Sets or gets the LogExtent holding the Unerased Space Bitmap.
//  checkValidity()
//      Returns an error if not valid.
//  error()
//      Returns any error in state.
//  logVolumep()
//      Sets or gets the pointer to the associated LogicalVolume
//  maxExtLen()
//      This returns the maximum allowed length of an extent in the
//      Partition.
//  spaceResourcep()
//      Gets or sets the pointer to the ISOSpaceResource associated
//      with this Partition.
//  validateSpaceExtents()
//      Returns an Error if the extents associated with the Space
//      Tables or Bitmaps are an illegal combination.
//  fromISO()
//      Initializes its state from the on-disk information.
//  toISO()
//      Dumps its current state into the on-disk structures.
//
// USAGE NOTES:
//  User notes go here.
// 
//----------------------------------------------------------------------
// COLLABORATORS:  
//  Contains a PartitionDesc.
//  Contains a PhysExtent.
//  Contains multiple LogExtents.
//  Points to a LogicalVolume.
//  Points to an ISOSpaceResource.
//
// PRIVATE DATA MEMBERS:
//  partitionDesc_        Holds the PartitionDesc.
//  partitionExt_         The physExtent this Partition occupies.
//  error_                Holds the error state.
//  erasedSpaceTblExt_    Extent holding Erased Space Table
//  erasedSpaceBMapExt_   Extent holding Erased Space Bitmap
//  unerasedSpaceTblExt_  Extent holding Unerased Space Table
//  unerasedSpaceBMapExt_ Extent holding Unerased Space Bitmap
//  logVolumep_           Pointer to the containing logicalVolume.
//  spaceResourcep_       Pointer to SR for this partition.
//
// IMPLEMENTATION NOTES:
//
//  Currently, the PartitionDesc is held INSIDE of the Partition
//  object. This is not required, and it should be noted that the
//  information about where the Space Bitmaps and Tables are written is
//  held in BOTH the pd AND the specific data members. The data members
//  of course override them.
//
//----------------------------------------------------------------------

class Partition {

    PartitionDesc      partitionDesc_        ;
    PhysExtent         partitionExt_         ;
    LogExtent          erasedSpaceTblExt_    ;
    LogExtent          erasedSpaceBMapExt_   ;
    LogExtent          unerasedSpaceTblExt_  ;
    LogExtent          unerasedSpaceBMapExt_ ;
    Error              error_                ;
    LogicalVolume    * logVolumep_           ;   
    ISOSpaceResource * spaceResourcep_       ;

  public:

    Partition( const PhysExtent & ext ) ;
    Partition( PhysicalVolume *pvp, UINT32 start, UINT32 numSectors ) ;
    ~Partition() {}

    // Getters of information about its physical extent
    UINT16 blockSize() const {
        return partitionExt_.sectorSize(); }
    UINT32 numBlocks() const {
        return partitionExt_.numSectors(); }
    UINT32 startSector() const {
        return partitionExt_.startSector(); }
    PhysicalVolume * physVolumep() const {
        return partitionExt_.physVolumep(); }

    // Erased Space Extent setters/getters
    void erasedSpaceTblExt ( const LogExtent & ext ) {
        erasedSpaceTblExt_ = ext; }
    LogExtent erasedSpaceTblExt ( void ) const {
        return erasedSpaceTblExt_; }
    void erasedSpaceBMapExt ( const LogExtent & ext ) {
        erasedSpaceBMapExt_ = ext; }
    LogExtent erasedSpaceBMapExt ( void ) const {
        return erasedSpaceBMapExt_; }

    // Unerased Space Extent setters/getters
    void unerasedSpaceTblExt ( const LogExtent & ext ) {
        unerasedSpaceTblExt_ = ext; }
    LogExtent unerasedSpaceTblExt ( void ) const {
        return unerasedSpaceTblExt_; }
    void unerasedSpaceBMapExt ( const LogExtent & ext ) {
        unerasedSpaceBMapExt_ = ext; }
    LogExtent unerasedSpaceBMapExt ( void ) const {
        return unerasedSpaceBMapExt_; }

    // Error methods
    Error checkValidity() const {
        return partitionExt_.error(); }
    Error error(void) const {
        if ( error_ )
            return error_;
        if ( partitionDesc_.error() )
            return partitionDesc_.error();
        else
            return partitionExt_.error();
    }

    // LVp setter/getter
    void logVolumep( LogicalVolume * lvp ) {
        logVolumep_ = lvp; }
    LogicalVolume * logVolumep(void) const {
        return logVolumep_;
    }
    UINT32 maxExtLen(void) const {
        return logVolumep_ ? logVolumep_->maxExtLen() : 0;
    }

    // SRp setters/getters
    void spaceResourcep( ISOSpaceResource * srp ) {
        spaceResourcep_ = srp; }
    ISOSpaceResource * spaceResourcep(void) const {
        return spaceResourcep_; }

    // Format legality
    Error validateSpaceExtents(void) const ;
    
    // To and From ISO methods
    void fromISO( const ByteArray &buf,
                  const PhysExtent & pext,
                  Error & error ) ;
    void toISO( ByteArray &buf,
                const PhysExtent & pext,
                Error & error ) ;
};

//----------------------------------------------------------------------
// CLASS: PhysicalVolume                    --DVM
//
//  A PhysicalVolume is the abstraction of an optical cartridge surface.
// 
//  PhysicalVolume objects are associated one to each surface of an
//  optical cartridge. Basically, they hold one or more partitions, and
//  make up a part of a PhysicalVolumeSet.
//
//  Its constructor requires a device object, because one cannot exist
//  without a method to access its media.
//
// PUBLIC METHODS:
//  PhysicalVolume()
//  physVolSetp()
//      Sets or gets the pointer to the associated PhysicalVolumeSet.
//  partitionp()
//      Sets or gets the pointer to the associated Partition.
//  driveDevp()
//      Sets the pointer to the associated SSDevice.
//  identifier()
//      Returns the PhysicalVolumeIdentifier.
//  volumeSetID()
//      Returns the PhysicalVolumeSetIdentifier.
//  read()
//      Reads the supplied physExtent from the PhysicalVolume.
//  write()
//      Writes the supplied physExtent to the PhysicalVolume.
//  writeWOE()
//      Writes the supplied physExtent without an erase pass to the
//      PhysicalVolume.
//  erase()
//      PhysicalVolume.
//      Erases the supplied physExtent on the PhysicalVolume.
//  checkValidity()
//      Returns an error if not valid.
//  error()
//      Returns any error in state.
//  sectorSize()
//      Returns the size of the sectors on the PhysicalVolume.
//  numSectors()
//      Returns the number of sectors on the PhysicalVolume.
//  fromISO()
//      Translates the supplied on-disk structure to the in-core
//      image.
//
// USAGE NOTES:
//  User notes go here.
// 
//----------------------------------------------------------------------
// COLLABORATORS:  
//  Contains a PrimaryVolumeDesc.
//  Contains an Error.
//  Points to a PhysicalVolumeSet.
//  Points to a Partition.  (multiple for multi-parts/surf.)
//  Points to an SSDevice.
//
// PRIVATE METHODS:
//  methodName()
//      Description_of_method
//
// IMPLEMENTATION NOTES:
//  Internal Notes go here (special cases, algorithm issues, etc.)
//
//----------------------------------------------------------------------

class PhysicalVolume {

    PrimaryVolumeDesc   priVolDesc_  ;
    Error               error_       ; // Internal error state
    PhysicalVolumeSet * physVolSetp_ ;
    Partition         * partitionp_  ; // Should be list for part/vol > 1.
    SSDevice          * driveDevp_   ;
    
  public:
    // Constructor
    PhysicalVolume(SSDevice *drive);
    ~PhysicalVolume();

    // Special initializers
    SSDevice * driveDevp( SSDevice *newdrive );

    // Setter/Getter pairs
    PhysicalVolumeSet * physVolSetp( void ) { return physVolSetp_; }
    PhysicalVolumeSet * physVolSetp( PhysicalVolumeSet *newpvsp );

    Partition * partitionp( void ) { return partitionp_; }
    Partition * partitionp( Partition *newpartp );


    // !!! volumeSetID should eventually go into PhysVolumeSet.
    String identifier( void ) {
        return priVolDesc_.volumeIdentifier;
    }
    void identifier( const String & vid ) {
        priVolDesc_.volumeIdentifier = vid;
    }
    
    String volumeSetID( void ) {
        return priVolDesc_.volumeSetID;
    }
    void volumeSetID( String & vsid ) {
        priVolDesc_.volumeSetID = vsid;
    }

    // Drive methods
    INT32 read( const PhysExtent & pe,
                const ByteArrayRef& ba,
                Error& err);
    INT32 write( const PhysExtent & pe,
                 const ByteArrayRef & ba,
                 Error& err);
    INT32 writeWOE( const PhysExtent& pe,
                     const ByteArrayRef& ba,
                     Error& err);
    INT32 erase( const PhysExtent & pe,Error& err );

    UINT16 sectorSize( void ) const { 
        return ( driveDevp_ == NULL ? 0 : driveDevp_->sectorSize() );
    }
    UINT32 numSectors( void ) const { 
        return ( driveDevp_ == NULL ? 0 : driveDevp_->numSectors() );
    }

    // Old-fashioned error method(s)
    Error error( void ) const {
        return ( error_ ? error_ : priVolDesc_.error() );
    }
    Error checkValidity( void );

    // ISO Methods
    void fromISO( const ByteArray &buf,
                  const PhysExtent & pe,
                  Error & err ) {
        priVolDesc_.fromISO( buf,0,pe.startSector() );
        err = priVolDesc_.error();
        return;
    }
    void toISO( ByteArray &buf,
                const PhysExtent & pe,
                Error & err ) {
        priVolDesc_.toISO( (BYTE_PTR)buf,pe.startSector() );
        err = priVolDesc_.error();
    }
};

//----------------------------------------------------------------------
// CLASS: SingleSurfaceVolume     --DVM
//
//  This class provides sorts through all of the on-disk volume
//  structures, instantiates the appropriate Structural Abstractions,
//  and ties them all together, ultimately providing access to all of
//  the following:
//
//  - The Root ICB Address
//  - A SpaceResource for the volume.
//  - The Integrity of the volume.
//  - The various names associated with the volume.
//
// PUBLIC METHODS:
//
//  fromDisk()
//      Builds a web of objects from the on-disk structures.
//  logVolumep()
//      Returns a pointer to the single LogicalVolume on the volume.
//  partitionp()
//      Returns a pointer to the single Partition on the volume.
//  sectorsInVol()
//      Returns the number of sectors in the PhyicalVolume.
//  physVolumeID()
//      Sets or gets the Name of the PhysicalVolume.
//  volumeSetID()
//      Sets or gets the Name of the PhysicalVolumeSet.
//  blocksInPartition()
//      Returns the number of blocks in the Partition.
//  blockSize()
//      Returns the size of the Logical Blocks.
//  blocksInLogVolume()
//      Returns the number of blocks in the LogicalVolume.
//  logVolumeID()
//      Sets or gets the Name of the PhysicalVolumeSet.
//  integSeqExtent()
//      Returns the first PhysExtent of the Integrity Sequence.
//  spaceResourcep()
//      Returns a pointer to the SpaceResource for this Volume.
//  RootICBAddr()
//      Returns a LogExtent where the Root Directory's ICB is located.
//  initOnDisk()
//      Initializes the volume with some fixed, default locations and
//      lengths.
//    
// USAGE NOTES:
//  User notes go here.
// 
//----------------------------------------------------------------------
// COLLABORATORS:  
//
//  Points to a SSDevice.
//  Points to a PhysicalVolume.
//  Points to a PhysicalVolumeSet.
//  Points to a Partition.
//  Points to a LogicalVolume.
//  Points to a FileSet.
//  Points to a ISOSpaceResource.
//  Contains an Error.
//
// IMPLEMENTATION NOTES:
//  
//
//----------------------------------------------------------------------

class SingleSurfaceVolume {
 
    SSDevice          * driveDevp_      ;
    PhysicalVolume    * physVolumep_    ;
    PhysicalVolumeSet * physVolSetp_    ;
    Partition         * partitionp_     ;
    LogicalVolume     * logVolumep_     ;
    FileSet           * fileSetp_       ;
    ISOSpaceResource  * spaceResourcep_ ;
    Integrity         * integrityp_     ;
    Error               error_          ;

    void free();
    
public:

// INLINE: SingleSurfaceVolume::SingleSurfaceVolume()
    SingleSurfaceVolume(SSDevice * ddevp) :
        driveDevp_      ( ddevp ),
        physVolumep_    ( NULL ),
        physVolSetp_    ( NULL ),
        partitionp_     ( NULL ),
        logVolumep_     ( NULL ),
        fileSetp_       ( NULL ),
        spaceResourcep_ ( NULL ),
        integrityp_     ( NULL ) {
    }

// INLINE: SingleSurfaceVolume::~SingleSurfaceVolume()
    ~SingleSurfaceVolume() {
        free();
    }

    //-----------------------------------------
    // Method for initializing from a volume
    //-----------------------------------------
    
    void fromDisk(Error & err);

    //-----------------------------------------
    // Method for initializing a new volume
    //-----------------------------------------

    void initDisk( const String & volID,
                   const String & volSetID,
                   const String & logVolID,
                   const String & fileSetID,
                   Error & err );
protected:

    // Supporting Volume Recognition Sequence
    void writeVRS( Error & err );

    // Supporting Allocation of volume space
    void allocVolSpace( PhysExtent& privdse,
                        PhysExtent& rsvvdse,
                        PhysExtent& lvidse,
                        PhysExtent& parte,
                        Error & err ); // grabs from entire volume space

    void allocPartSpace( LogExtent& fsdse,
                         LogExtent& ricbe,
                         Error & err ); // grabs from current SR.
    
    // Supporting Volume Descriptor Sequence
    void writeAVDPs( const PhysExtent& privdse,
                     const PhysExtent& rsvvdse,
                     Error & err );
    void writePVDs( const String & volID,
                    const String & volSetID,
                    PhysExtent & privdse,
                    PhysExtent & rsvvdse,
                    Error & err );
    void writePDs( Partition * partp,
                   PhysExtent & privdse,
                   PhysExtent & rsvvdse,
                   Error & err );
    void writeLVDs( const String & logVolID,
                    const PhysExtent & lvidse,
                    const LogExtent & fsdse,
                    PhysExtent & privdse,
                    PhysExtent & rsvvdse,
                    Error & err );
    void writeOVDs( const String & logVolID,
                    PhysExtent & privdse,
                    PhysExtent & rsvvdse,
                    Error & err );
    void writeUSDs( PhysExtent & privdse,
                    PhysExtent & rsvvdse,
                    Error & err );
    void writeTDs( PhysExtent & privdse,
                   PhysExtent & rsvvdse,
                   Error & err );

    // Supporting File Set Descriptor
    void writeFSD( const String & fileSetID,
                   const String & logVolID,
                   const LogExtent & rootNodeAddr,
                   const LogExtent & fsdse,
                   Error & err );

    // Supporting the root directory
    void writeEmptyRootDir( LogExtent & rootNodeAddr,
                            Error & err );

    // NOTE: SpaceResource and Integrity objects support going toDisk()
    // separately, so they have no private support methods.
                    
public:    

    //-----------------------------------------
    // Methods allowing access to its components
    //-----------------------------------------

    LogicalVolume * logVolumep( void ) { return logVolumep_; }
    Partition * partitionp( void ) { return partitionp_; }

    //-----------------------------------------
    // Methods for info on the DriveDevice:
    //-----------------------------------------

#ifdef OLD_CODE_DVM
    Error checkDriveValidity() const {
        if ( driveDevp_ == NULL )
            return Error(error_DriveDevice_invalid);
        else
            return driveDevp_->checkValidity();
    }
#endif
    
    //-----------------------------------------
    // Methods for info on the PhysicalVolume:
    //-----------------------------------------
#ifdef OLD_CODE_DVM
    Error checkPhysVolumeValidity() const {
        if ( physVolumep_ == NULL )
            return Error(error_PhysicalVolume_invalid);
        else
            return physVolumep_->checkValidity();
    }
#endif
    
    UINT32 sectorsInVol() const {
        if (physVolumep_ != NULL)
            return physVolumep_->numSectors();
        else
            return 0;
    }

    String physVolumeID() const  {
        if (physVolumep_ != NULL)
            return physVolumep_->identifier();
        else
            return String("");
    }
    
    void   physVolumeID( const String & );

    //-----------------------------------------
    // Methods for info on the PhysicalVolumeSet:
    //-----------------------------------------

    // !!! volumeSetID should eventually come from PhysVolumeSet.
    String volumeSetID() const {
        if (physVolumep_ != NULL)
            return physVolumep_->volumeSetID();
        else
            return String("");
    }
    
    void   volumeSetID( const String & );

    //-----------------------------------------
    // Methods for info on the Partition:
    //-----------------------------------------

#ifdef OLD_CODE_DVM
    Error checkPartitionValidity() const {
        if ( partitionp_ == NULL )
            return Error(error_Partition_invalid);
        else
            return partitionp_->checkValidity();
    }
#endif
    
    UINT32 blocksInPartition() const {
        if (partitionp_ != NULL)
            return partitionp_->numBlocks();
        else
            return 0;
    }

    //-----------------------------------------
    // Methods for info on the LogicalVolume:
    //-----------------------------------------

#ifdef OLD_CODE_DVM
    Error checkLogVolumeValidity() const {
        if ( logVolumep_ == NULL )
            return Error(error_LogicalVolume_invalid);
        else
            return logVolumep_->checkValidity();
    }
#endif
    
    UINT32 blockSize() const {
        return logVolumep_->blockSize(); }
    UINT32 blocksInLogVolume() const {
        return logVolumep_->numBlocks(); }

    String logVolumeID() const {
        if (logVolumep_ != NULL)
            return logVolumep_->identifier();
        else
            return String("");
    }

    void logVolumeID( const String & );

    PhysExtent integSeqExtent( Error & err ) {
        if (logVolumep_ != NULL)
            return logVolumep_->integSeqExtent(err);
        else
            return PhysExtent(physVolumep_,0,0); // empty extent
    }

    //-----------------------------------------
    // Methods for info on the Integrity
    //-----------------------------------------

    Integrity * integrityp(void) {
        return integrityp_;
    }

    //-----------------------------------------
    // Methods for info on the SpaceResources:
    //-----------------------------------------

    ISOSpaceResource * spaceResourcep(void) {
        return spaceResourcep_;
    }

    //-----------------------------------------
    // Methods for info on the FileSet:
    //-----------------------------------------

#ifdef OLD_CODE_DVM
    Error checkFileSetValidity() const {
        if ( fileSetp_ == NULL )
            return Error(error_FileSet_invalid);
        else
            return fileSetp_->checkValidity();
    }
#endif

    String fileSetID() const {
        if (fileSetp_ != NULL)
            return fileSetp_->fileSetID();
        else
            return String("");
    }
    
    LogExtent rootICBAddr(Error & err) const {
        return fileSetp_->rootICBAddr(err);
    }
    
};

//----------------------------------------------------------------------
// METHOD: SingleSurfaceVolume::SingleSurfaceVolume()   --DVM
//
//  Constructor for SingleSurfaceVolume object.
//
// ARGS:
//
//  DriveDevice *ddp  IN  This is a pointer to an already-constructed
//                       DriveDevice object.
//
// PRECONDITIONS:
//
//  --The DriveDevice passed in must exist, be accessible, and be a
//    valid device.
//  
// ERRORS:
//
//  error_None:  Function completed successfully.
//  error_DriveDevice_invalid: bad DriveDevice supplied.
//
// NOTES:
//
//----------------------------------------------------------------------

//----------------------------------------------------------------------
// METHOD: SingleSurfaceVolume::~SingleSurfaceVolume()  --DVM
//
//  Destructor for SingleSurfaceVolume object.
//
// ARGS:
//
//  none
//
// NOTES:
//
//  This function destroys all the objects constructed by it.
//  This does NOT include the DriveDevice, but DOES include all the
//  others to which it points. Note that these must be deleted in the
//  reverse order from which they were built.
//----------------------------------------------------------------------

#endif // _NSRSSVOL_
