next up previous contents
Next: Implementation Notes Up: An Example Class Previous: An Example Class

Connecting to Files

The binding mechanism enables ADI class instances to map onto file system objects such as HDS components, or FITS arrays, extensions or keywords. The easiest way to understand is by way of an example. The Array class will be extended to handle HDS primitive arrays and FITS primary arrays.

The routine ADI uses to connect existing file system objects to an ADI class is adi_fopen, which looks like this,

   adi_fopen( fspec, mode, class, id, status )
where fspec is the path to the file object, mode is the access mode and class is the ADI class we expect to open. For our Array example we want something like,
   adi_fopen( 'myfile.data_array', 'READ', 'Array', aid, status )
ADI opens the object named in the first argument with access mode provided in the second, but is then stuck. It has to know how to connect the fact that it has a locator to a primitive HDS array to an ADI class instance. ADI has a concept of a "natural class" for a file object, ie. that ADI class which most closely matches the way the data is stored on disk. We can extend ADI's knowledge of these matches at run-time by defining a callback routine. A callback is simply a routine which is not executed immediately, but later when it is needed. The way this is done is,
  external adi1_isarray

  adi_defrcb( 'HDS', 'Natural', adi1_isarray, status )
The adi_defrcb routine defines a callback for a particular file representation. The callback function must have one of the predefined names listed in Appendix gif. The callback routine has an extra digit after the adi and before the underscore. This flags it as an internal routine, and the value indicates that it is HDS specific. Callback routines have fixed argument lists and the definition for a Natural callback is the following,
   <natural_callback>( id, class, status )
     integer       id
     character*(*) class
The id argument is the identifier of the File ADI has connected to your named file. The purpose of the routine is to try and derive a value for class. Here is a pseudo-code version of adi1_isarray,
   subroutine adi1_isarray( fid, class, status )
     integer       fid
     character*(*) class

     extract locator from FID
     use HDS routines DAT_PRIM and DAT_SHAPE to see if the object is 
       a primitive array
     if it is,
       class = 'Array'
     else
       class = ' '
   end
ADI now knows that the user has requested an Array and that it has a file object whose natural class is also Array Putting 2 and 2 togther ADI now has to create the instance of an Array class which has a binding to the File . This is done using another callback, but one which is specific to a particular class.
  external ari1_open

  adi_defccb( 'Array%HDS', 'Open', ari1_open, status )
The purpose of this routine is to write the values of the mandatory keywords into the empty Array instance. The syntax of the first argument tells ADI that this routine should only be applied to an Array object bound to an HDS based File .
   subroutine ari1_open( fid, id, status )
     integer fid,id

     extract locator from FID
     use DAT_SHAPE and DAT_TYPE to define the SHAPE and TYPE keywords     
   end
There are two fundamntal ways of implementing file interface objects. The first and by far the simplest to program is imply to copy all the file data objects into memory on read, writing them out again if required. In reality this would be far too slow and use too much memory and a complex scheme which converts ADI accesses to the class instance object into file system access calls is required.

To make the mapping between the memory based Array object and the file based HDS array useful we must now overload the the various data access methods used by ADI. To simply read the values from a class data member the adi_mget routines are used, eg.

   adi_mget1r( aid, 'Data', maxval, my_reals, nactval, status )
The adi_mget routine is implemented by invoking the Get method on the named class data member. This can be overloaded using the callback mechanism,
  adi_defccb( 'Array%HDS', 'Get(Data)', ari1_getdata, status )

  subroutine ari1_getdata( id, mem_hdl, status )
    integer    id
    integer    mem_hdl

    get locator from ID
    check data is valid
    get memory space TYPE, DIMS and PTR from MEMHDL
    DAT_GET the data to the address PTR
  end



next up previous contents
Next: Implementation Notes Up: An Example Class Previous: An Example Class



Web Master
Wed Oct 8 09:22:23 BST 1997