9/81 PRM-11 USER'S GUIDE OMSI PASCAL INTERFACE TO RMS-11 Kenneth G. Tibesar 3M Engineering Systems and Technology Labs St. Paul, Minnesota 55144  Pascal Record Management User's Manual Page 2  Table Of Contents 1.0 Introduction To PRM 1.1 PRM Design 1.2 User Interface 1.3 File Operations 1.4 Record Operations 1.5 RFA 1.6 Memory Requirements 2.0 Preparing for PRM 2.1 Pre-defined Data Structures 2.2 Control Buffers 2.2.1 RmsFileDesc - File Description 2.2.2 RetRecord - Record Retrieval 2.2.3 StoRecord - Record Storage 2.2.4 IdxKeyDesc - Indexed Key Description 2.3 Record Buffers 2.3.1 Non-Shared Buffers 2.3.2 Shared Buffers 2.4 Key Buffers 2.5 PRM External Calls 2.6 Rms-11 Initialization 2.7 Task Build 2.8 User Space Optimization 2.9 PRM Pit-Falls 2.9.1 Record Size 2.9.2 Rms Initialization 2.9.3 File Sharing 3.0 Detailed Description of PRM Buffers 3.1 RmsFileDesc - File Description 3.2 RetRecord - Record Retrieval 3.3 StoRecord - Record Storage 3.4 IdxKeyDesc - Indexed Key Description 3.5 User Defined Record Buffers 4.0 Detailed Description of PRM Routines 4.1 General Use 4.2 File Access and Creation 4.2.1 PRMClo 4.2.2 PRMCre 4.2.3 PRMKey 4.2.4 PRMOpe 4.3 Record Retrieval and Storage 4.3.1 PRMDel 4.3.2 PRMFre 4.3.3 PRMRet 4.3.4 PRMSto Appendix A PRM program example - Access an existing RMS files Appendix B PRM program example - RMS indexed file creation Appendix C Command and Overlay descriptor files example Appendix D PRM Error Codes  Pascal Record Management User's Manual Page 3  Preface PREFACE Record Management Services (RMS-11) is a software package written and supported by DEC. The package is a data management tool that supports sequential, relative and indexed (ISAM) files. Pascal Record Management (PRM-11) is a non-supported interface developed by 3M Engineering and Systems Technology Labs. PRM was developed as an interim until the OMSI Pascal Compiler directly supports RMS-11. PRM was developed and tested using V1.2G of OMSI Pascal and DEC RSX-11M+ operating system. Known problems will occur when using OMSI Pascal V1.2H due to changes in initialization procedures. Version 2 of OMSI Pascal can be used only if the Version 1 switch is used. Comments and questions concerning PRM should be directed in writing to: Kenneth Tibesar 3M Center, Bldg. 518-1 St. Paul, Minnesota 55144 Please - No Phone Calls CHAPTER 1  Introduction to PRM PRM-11 is a set of routines written in OMSI Pascal with in-line MACRO-11 code to interface to RMS-11. DEC supported high level languages interface to RMS-11 by using key words supported by the language compiler. The present versions of OMSI Pascal for the PDP-11 do not support RMS-11 interface. PRM provides the interface via a set of external procedures that are similiar to the key words used by DEC languages. PRM routines are called by the user code when RMS-11 operations are required. The PRM routines are linked to the user code during the task build. 1.1 PRM Design PRM routines use DEC supported MACRO-11 routines to perform RMS-11 operations. RMS-11 requires attribute blocks describing the file (FAB) and record (RAB). PRM defines fields within the attribute blocks. This allows Pascal to directly control the contents of the files RABs and FABs. The contents of the RABs and FABs are indirectly controlled by the PRM user by loading pre-defined buffers and using one of the PRM external procedures. User buffers required by PRM routines are allocated in the user space. The user defines only the number of buffers required for the application. The buffers are loaded by the PRM user to indicate file or record access parameters. The buffers are also used by PRM as working space. By using buffers allocated globally (from the heap), PRM can preserve variables between PRM calls. Normally, RMS-11 requires the user to reserve POOL space. The POOL space is used by RMS internal code as control structures known as BDB's (Buffer Descriptor Blocks). The POOL space has to be allocated based on the number of simultaneously opened files. This design would waste user space that cannot be reclaimed even though the file is closed.  Pascal Record Management User's Manual Page 1-2  Introduction to PRM To avoid this loss of valuable user space, PRM dynamically allocates and de-allocates the space when required by RMS-11. RMS-11 allows the MACRO-11 programmer to specify a GSA (Get Space) routine. The PRM GSA routine simply calls the Pascal Run-Time-System NEW and DISPOSE routines to manage HEAP space. RMS-11 uses the declared GSA routine when it requires or releases space. Space is not used until a file is opened and returned to the Pascal heap when the file is closed. PRM was modeled after syntax used by existing DEC supported languages that interface to RMS-11. The following is a list of PRM and high level language comparisons: 1. DEC - Compilers support commands that perform RMS-11 file and record operations. PRM - External procedures linked to the Pascal program perform RMS-11 file and record operations. 2. DEC- Descriptive key words are used with RMS-11 commands to specify attributes of the file and record operations. PRM - Descriptive field names are used to load records passed to the external procedures. The record fields specify attributes of the file or record operation. 3. DEC - A completion code indicating the success or failure of each RMS operation is made available to the user. The completion code is available through the use of a reserved word. PRM - A completion code is returned with each PRM call. The code is the standard RMS-11 completion code. In addition, PRM provides debugging completion codes for the PRM programmer. 1.2 User Interface The PRM interface to OMSI Pascal uses the Pascal internal record structure to pass data. Pre-defined records are included in the TYPE declaration of the User Pascal program. The Pascal programmer determines the operation to be performed (open, close, get record, etc.) and loads the appropriate record buffer. Once loaded, the record address is passed to the specific PRM routine that performs the file or record operation. The PRM routines load the RMS attribute blocks (RAB and/or FAB) with the control codes necessary to satisfy  Pascal Record Management User's Manual Page 1-3  Introduction to PRM the user request. If data is to be stored or retrieved, the User Pascal program is also required to pass the address of a data buffer. The data buffer is loaded with data retrieved or the contents stored. In addition to control and data buffer addresses, an address of a status buffer is required with all PRM calls. The status buffer is loaded with a completion code. The code is a standard MACRO-11 RMS success/error code (refer to RMS-11 User's Manual, Appendix B). In addition PRM will return debugging error codes for the PRM user. PRM error codes are only generated due to PRM user program procedural errors. Refer to Appendix D for detail on PRM error codes. The user should check the completion code following each PRM call. If the file is not opened properly, no record operations should be performed. If the user continues after an error in a file open or creation, PRM will catch the error. All record operations on an improperly opened or created file are prohibited. Any call that attempts access to an improperly opened file will be rejected and a PRM error code will be returned. 1.3 File Operations There are four file operation primitives provided. A buffer of TYPE RmsFileDesc is used with all the PRM file routines. The PRM user must allocate a buffer of this TYPE for each simultaneously open file. The buffer is loaded by the PRM user to describe the file to be opened or created. Once the file is open, the contents of this buffer provide space for the file attributes blocks (FAB and RAB). The attributes blocks are loaded by PRM routines to indicate PRM User requests to RMS-11 routines. All PRM record operations require the PRM User to pass the address of the RmsFileDesc buffer. This indicates to PRM the file to be accessed. Space in the RMSFileDesc TYPE buffer is used is as the file and record attributes blocks (RAB and FAB). Allocation of user space for the file attributes blocks allows PRM to preserve the file and record attributes between PRM calls. The file operation primitives are: 1. PRMClo - Closes an open RMS file and returns used buffer space to the Pascal heap. 2. PrmCre - Creates an Rms File. If the file to be created is an indexed (ISAM) file, the PRMKey routine  Pascal Record Management User's Manual Page 1-4  Introduction to PRM must be called a minimum of one time prior to this call. 3. PRMKey - Defines the keys of an indexed file. This call is used prior to the PRMCre routine. Each call defines a key of the indexed file. Multiple keys must be defined in ascending order. In addition to the RMSFileDesc buffer, a buffer of TYPE IdxKeyDesc is also used with the PRMKey routine. 4. PRMOpe - Opens an existing RMS file PRM insures that the user knows the file record size of the file specified for during PRMOpe. The open requires the user to specify the record size of the file. If the actual file record size and the user specified record size to not match, any activity on the file is prohibited. PRM returns the standard RMS-11 Macro error codes for all of the above calls. 1.4 Record Operations There are four record operation primitives provided by the PRM interface. An address of buffer TYPE RetRecord is passed to PRMRet. An address of buffer TYPE StoRecord is passed to PRMSto for storing records. The buffers contain the necessary parameters for access to the file. Record Operation PRM procedures require the user to pass the address of the RMSFileDesc TYPE buffer with each call. The file RAB and FAB are defined for the open file in the RMSFileDesc buffer. PRM interprets the user record operation request and loads the appropriate RAB fields. The RMS-11 Macro is then called and RMS-11 performs the record operation. Before the record operations are performed, PRM will check to see if the file to be accessed is properly opened. Record operations performed on an improperly opened file will produce unpredictable results. Any record operation request performed on an RMS file that has not been successfully opened by PRMOpe or PRMCre will be rejected by PRMRet and PRMSto. The record operation primitives are: 1. PRMDel - Delete the currently selected record from the file. The currently selected record is established with a PRMRet call.  Pascal Record Management User's Manual Page 1-5  Introduction to PRM 2. PRMFre - Unlocks the bucket locked by the previous PRMRet operation. The bucket is locked only if the file is opened with write access. 3. PRMRet - Retrieves a record from a file successfully opened with PRMOpe. A record is always placed in the RMS I/O internal buffer. If a PGET type retrieval is executed, the User Record Buffer (address passed by the PRM user) is loaded. If a PFIND type retrieval is executed, the user record buffer is not loaded. 4. PRMSto - Store or update a record in a sucessfully opened file. A PPUT operation will generate a new record, a PUPDATE will update an existing record. 1.5 RFA (Record File's Address) The PRM interface provides access to file records via RFA's. An RFA is a unique number assigned to each record of RMS type files. The use of RFA provides direct access to a record by-passing the record processing software. Use of an RFA will also provide random access to RMS Sequential files that are stored on random access devices (disks). An example of RFA access usage would be an application that searches the file for records with specific conditions. The entire file is searched and records with the specified conditions are internally stored for future reference. When the entire file has been searched, the processing begins randomly accessing the file for the specified records. If during the initial search, the RFA is stored, the RFA can be used to randomly access the records. The storing of the RFA may be an alternative to storing the entire record (or key) in memory for rapid access to the data after the initial search. Storing the entire record (or key) may not be possible due to space limitations. The previous scenario describes the use of DataTrieve when forming a "collection". NOTE The RFA used to define a record is unique and can be stored in a file for access to records for subsequent executions of an application. However, the RFA is only valid for the life of the file. Once the file has been reorganized with a utility  Pascal Record Management User's Manual Page 1-6  Introduction to PRM such as CNV or IFL, the RFA for a given record is no longer valid. RFA's can be used to retrieve records only. When you store a new record, PRM returns the RFA generated by RMS. When you retrieve a record with normal access, the record RFA is returned by PRMRet. When you retrieve a record by RFA, you specify search = RFA in RetRecord buffer and load the RFA in KeyNum in RetRecord buffer. Refer to paragraphs 3.2 and 3.3 for description of the buffers used to pass RFA's between PRM and the user code. Refer to Appendix A for an example program using RFA random access with a sequential file. 1.6 Memory Requirements Additional code is required by any interface to RMS-11. Code must set-up the FAB and RAB fields to indicate the request to RMS-11. PRM code requires approximately 1KW if all routines are used. PRM is designed so only the required calls are included. Dynamic memory space is managed by the Pascal run-time system. PRM defines a GSA routine (refer to paragraph 1.1) to efficiently control allocation and deallocation of Pascal heap space. RMS-11 code requires approximately 24KW is all file organizations with all RMS-11 file and record operations supported. At present, PRM requests the task builder to link ALL RMS-11 code to a PRM task. If the RMS-11 Resident Library is not used, the user space remaining is severly limited. If not using RMS-11 Resident Library support, modify the RMSIni routine and/or use DEC supplied ODL (overlay descriptor language) files. Refer to paragraphs 2.5 and/or 2.6 for detail. CHAPTER 2  Preparing for PRM The PRM User Program must include the PRM interface structures and external procedure calls in the User Pascal source program. All the structures and calls are provided as part of the PRM package. The data structures are located in file PrmPrefix.Pas. The PRM Procedure calls are located in file PrmCalls.Pas. The following is an abbreviated list of the steps that must be followed to prepare your task for interface to PRM-11. Paragraphs that follow detail each step. 1. Pre-Define Data Structures - Pre-defined data structures must be included in your source code. The data structure are located in file PRMPrefix.Pas. 2. Control Buffers - Allocate space in your task by defining buffers of TYPES defined from the data structures file. The buffers are used to pass control data to PRM external routines. Define only the buffers required to satisfy PRM interface requirements. 3. Record Buffers - Define data structures to describe the logical record of your application. An example record definition is included in the data structures file. Allocate the required record buffers to satisfy task requirements. 4. Key Buffers - Modify the KeyDef record definition and keysizes in CONST to describe the keys of your indexed and/or relative file(s). Use variant records to define key(s) of the RMS file(s). If your application uses RELATIVE type files, define one entry of type "TwoWord" (defined in PRMPrefix) to hold RELATIVE record numbers for retrieval and store operations. 5. External Calls - Include the contents of file PRMCalls.Pas. Delete PRM procedure call(s) that will  Pascal Record Management User's Manual Page 2-2  Preparing for PRM not be used. This will avoid the addition of code that will not be used. 6. RMS-11 Initialization - Modify RMSIni if all file organizations and/or record operations are not used. This is important if you are NOT using the RMS Resident Library. 7. Task Build - Reference object library PRMPAS during task build. 8. User Space Optimization - Share control and data buffers if space is limited. 9. PRM Pit-Falls - Check to make sure your task has specified the proper parameters to PRM. 2.1 Pre-defined Data Structures File PRMPrefix.Pas defines all of the data structures that are used to pass user specified data to PRM routines. Data is transferred to external routines by passing an address reference of control buffers allocated in the main program space. PRM routines expect a specific format of the buffer therefore PRM external procedures and user programs must use formatted records. The buffer descriptions used by PRM routines and PRM Users are not exactly alike. For example, PRM routines fully define the RAB and FAB in the RMSFileDesc buffers. The user RMSFileDesc buffer defines the RAB and FAB as "work space". This difference allows the user to ignore fields within the RAB and FAB. The complexity of the user program is reduced because pointer types in the RAB and FAB are defined externally only. Another difference is the record and key buffer definitions. PRM determines the size by using size data passed by the user. PRM has to depend on the user to specify the proper sizes. 2.2 Control buffers The control buffers provide the user with a means of specifying control data to PRM external routines. PRM uses the control data loaded by the user to load the RMS-11 RAB (record attributes block) and FAB (file attributes block). Codes are generated by PRM to indicate user requests passed  Pascal Record Management User's Manual Page 2-3  Preparing for PRM via the control buffer fields. 2.2.1 RMSFileDesc - File Description The RMSFileDesc (RMS File Description) type buffer is allocated by the user in the main program space (heap space). A buffer is allocated for each simultaneously open file (refer to paragraph 2.2.9). The buffer is loaded by the user before the PRMOpe (open file) procedure is called. All proceding PRM calls pass the address of this buffer to the PRM routine to indicate the file to be used for the record operation. The RMSFileDesc buffer provides PRM with space that is used as the file RAB and FAB. Since the buffer is allocated from the user space (versus locally allocated), the contents of the RAB and FAB can be preserved between PRM calls. 2.2.2 RetRecord - Retrieval Record The RetRecord (Retrieval Record) type buffer defines the user retrieval parameters. PRM also uses fields in the buffer to pass back control data to the calling program. The PRM user loads the buffer prior to each PRMRet (record retrieval) call. 2.2.3 StoRecord - Storage Record The StoRecord (Store Record) type buffer defines the parameters used when storing a record in an open file. The buffer is used with PRMSto (store record) external procedure. 2.2.4 IdxKeyDesc - Indexed Key Description The IdxKeyDesc (Indexed File Key Description) type buffer is used to define each key of a dynamically created RMS-11 indexed file. A buffer of this type is loaded prior to using the PRMKey (key definition) external procedure.  Pascal Record Management User's Manual Page 2-4  Preparing for PRM 2.3 Record buffers The PRM user defines record buffers to hold the file logical records. One record buffer can be allocated for each file or record buffers can be shared. The address of the record buffer and size of the record buffer is passed to the PRMRet or PRMSto external procedures. The external procedures use the size and address of the buffer to load or store the data. Size of the record buffer specified by the user cannot be checked for accuracy by PRM external procedures. If care the user specifies an incorrect buffer size, FATAL results can occur. Refer to paragraph 2.2.9 for details. 2.3.1 Non-shared record buffers If your program logic requires record data from more than one file simultaneously, serparate record buffers have to be allocated. Buffers of the same type have to be allocated to satisfy Pascal type checking. The type checking if enforced when passing the buffer to the external PRM procedures. Modify the RecDef buffer definition in PRMPrefix.Pas to satisfy your requirements. Use as many CASE entries as required to specify all record buffer types. If your application does not require the file full record, allocate the size of the buffer required. When you perform record operation specifying a RecSize in the RetRecord or StoRecord buffers before the operation. In some cases, your application the record buffer sizes may differ significantly. Using a variant record definition may not be desirable due to allocation of the largest variant for each buffer. This means that the smaller record buffer will have an unused space the size of the difference in record sizes. If the logical records of your application vary in size and you cannot afford wasted space, define a separate record TYPE for each record. To satisfy Pascal TYPE checking when the buffer is passed to external PRM procedures, define the PRMRet and/or PRMSto call(s) local to a user procedure. The locally defined procedure call will be the same as the globally defined call with the exception of the record TYPE definition. The external procedure call will be linked to the same PRM external procedure by the task builder.  Pascal Record Management User's Manual Page 2-5  Preparing for PRM 2.3.2 Shared record buffers If your application does not require data from different files simultaneously, the same record buffer can be used to hold data from more than one file. A record buffer address is passed to PRM procedures that store (PRMSto) or retrieve (PRMRet) records. The record buffer used is dynamically determined by the calling program. 2.4 Key Buffers Modify the KeyDef TYPE description to define the keys of you file(s). A CASE of all the TYPEs can be defined. The RetRecord type buffer uses the KeyDef description to determine the key structure. Since the RetRecord places the KeyDef type field at the end of the RetRecord buffer, the key can be any size. 2.5 PRM External Calls External procedure calls are defined in file PrmCalls.Pas. Only the calls used in your application should be included in your source code. The task builder will include the PRM code form the PRM library for only the calls referenced in the source. Define the PRM procedures local to user procedures if different record TYPE buffers are required. Refer to paragraph 2.3.1 for details. 2.6 RMS-11 Initialization There is only one initialization routine, RMSIni. This module must be referenced in all tasks using PRM. RMSIni defines a RMS-11 Macro that indicates to the task builder the RMS-11 code that has to be linked to the task. The PRM package assumes worst case and specifies that all file organizations with support for all operations. If the user links to the RMS-11 Resident library, the support of one or all file organizations and operations requires the same amount of space (8KW, 2 APR's) from the user task. If the RMS-11 Resident library is not supported on your system, the RMS-11 code would require approximately 24KW of user space.  Pascal Record Management User's Manual Page 2-6  Preparing for PRM If you DO NOT link to the RMS-11 Resident library, you should do the following: 1. Make your own copy of file RMSIni.Src to be used by your task(s) with the same file access requirements. Change the file name to make sure your task references your copy of RMSIni. 2. Modify the entries following the $ORG MACRO. Refer to the RMS-11 Macro-11 Reference Manual, paragraph 1.1.2. Specify only the file organization(s) and file access operations required by your task. 3. Compile and assemble the modified module. 4. Reference the module in your source code. 5. Reference the modified module during the task build. 6. Use one of the standard RMS overlay descriptor files. Refer to the RMS-11 User's Guide, chapter 8. In addition to indicating the code that is to be linked to the task, RMSIni also specifies a dynamic memory management routine. The routine is defined to RMS-11 as a GSA (Get Space) routine. It is essential that RMSIni be located in the .ROOT segment of an overlayed task. The routine has to be available for RMS-11 at all times. It is also essential that the RMSIni routine be executed one time prior to any other PRM routines. 2.7 Task Building When task building, the PRMPAS.OLB must be referenced in the task builder command or overlay description file. If you are using the RMS-11 Resident library, use the DEC supplied overlay description and reference RMSRES with the RESLIB command file option. If you are using overlays, select one of the standard DEC supplied overlay description files or use the DEC supplied command file MAKRMSODL.CMD to help tailor an ODL file to fit your specific needs. An example of a command and ODL file is provided in Appendix C.  Pascal Record Management User's Manual Page 2-7  Preparing for PRM 2.8 User Space Optimization If your application requires access to files that are not opened simultaneously, file buffer of TYPE RmsfileDesc can be used for more than one file. It is important that a file be closed successfully before the buffer is used for another file. In most cases, the RetRecord and StoRecord TYPE buffers can be shared with no problems. Only when it is more efficient to maintain access attributes for separate files should separate buffers be allocated. User record buffers can be shared to reduce the space used. Paragraph 2.3 details shared and non-shard user record buffers. The RMSIni routine should be modified to fit your application requirements. Paragraph 2.5 describes the modifications to RMSIni. 2.9 PRM Pit-Falls PRM routines perform error checking to make certain that the PRM User follows RMS-11 and PRM usage guide lines. There are, however, certain guidelines that cannot be checked because PRM routines are serperatly compilied. PRM has to depend on the PRM user for items listed below. If the minimum requirements listed below are not met, unpredictable errors will result. 2.9.1 Record Size PRM routines depend on the PRM User to supply the record buffer. The user also has to supply PRM routines with the size of the record buffer. Since PRM routines are external, compiled separately and a general set of routines supporting any RMS file, there is no way that the routines can accuratley check buffer sizes allocated in the MAIN PRM User program. PRM depends on the PRM User to inform the external routines of the size of the record to be retrieved or stored. If the PRM User defines a record size that is larger than the record buffer actually allocated, PRM (RMS) has to assume the record size is correct. When a record is retrieved from the file user code (or data) will be destroyed if the allocated buffer is smaller than the record retrieved from the file.  Pascal Record Management User's Manual Page 2-8  Preparing for PRM PRM checks the user record size specified in the RMSFileDesc TYPE buffer when the file is opened. The user must specify the exact file record size. This is to ensure characteristics of the file being opened are known. A PRM error code will be returned if the file and user declared record size do not match. This, however, is only a check and does not ensure that user code will not be destroyed. The PRM user should define a CONSTANT to define the size of the logical record buffer. The same CONSTANT should be loaded into the RMSFileDesc buffer before the PRMOpe. 2.9.2 RMS Initialization If the RMSIni routine is not executed first in your task, unpredictable results will occur. RMS-11 assumes the the GSA routine (declared within the RMSIni module) is constantly available for use. If the GSA routine is not in the .ROOT segment of your task, RMS-11 will fail. Refer to paragraph 2.4 for detailed information concerning modification of RMSIni. 2.9.3 File Sharing If the file being accessed is to be used by multiple tasks simultaneously, and your tasks specifies write access to the file, the target bucket of a record access will be locked. When a bucket is locked, the records in the bucket are not accessable by other users. When your application has completed the access (or timed-out if waiting for an event), the bucket should be released by executing the PRMFre routine. If your application specifies READ access to the file, buckets are never locked. CHAPTER 3  Detailed Description of PRM Buffers This chapter gives detailed description of all the PRM pre-defined buffers that have to be used for the PRM interface. Brief descriptions of the fields of each buffer are provided. Detailed description of file and record attributes requested by each field can be located in the RMS-11 User's Guide. 3.1 RmsFileDesc - File Description The following describes the fields in the RMSFileDesc type buffer that are used to create an RMS-11 file. 1. ORG - File Organization 1. Description : The file organization of an existing file to be opened or a file to be created. Use one of the key word scalar types to define a Sequential (SEQ), Relative (REL) or Indexed (IDX) file. 2. Default : None 2. FileName - File Name 1. Description : Full file specification of the file being created. The file specification is defined by the operating system being used. 2. Default : None 3. LogChan - Logical Channel Number 1. Description : The logical channel number for the file I/O operations. Refer to the task builder  Pascal Record Management User's Manual Page 3-2  Detailed Description of PRM Buffers manual, UNITS description in the Options paragraph. 2. Default : None 4. Allow - System File Access 1. Description : What other tasks can do to this file while you have the file open. If you want exclusive access to the file specify NOSHARE. If you will allow others to open the file, specify SHARE. If any other task has previously opened the file with NOSHARE, an error will be returned when you attempt to open the file. 2. Default : Share 5. Access - Program Access 1. Description : Specifies what the program opening the file can do while the file is open. Specify PREAD for read only, PWRITE for write only and PBOTH for both read and write access. If either PWRITE or PBOTH is specified, target buckets are locked. The bucket remains locked until another target bucket is specified or the PRMFre call is used. If the file is shared, bucket locking for long periods of time should be avoided. 2. Default : Read Only 6. RecordSize - File Record Size 1. Description : The full size of the record of the file being created or opened. This should be defined as a CONSTANT and also be used to define the size of the logical record buffer used. If an existing file is being opened, the exact file record size has to be specified or a PRM error code will be returned. 2. Default : None 7. DeferWrite - Deferred Bucket Write to File 1. Description : Valid for indexed files only. Normally storage of each logical record causes the contents of the entire RMS bucket to be stored in the file to ensure the contents of the  Pascal Record Management User's Manual Page 3-3  Detailed Description of PRM Buffers file contain the most up-to-date data. If deferred write is selected, the bucket will not be written to the file until the bucket is full. 2. Default : No Deferred Write 8. Unlock - Unlock the file 1. Description : The file will not be locked as a result of the improper closing of the file due to program abort. This should NOT be used for RMS Sequential files. 2. Default : Lock the file if improperly closed 9. ObeyFill - Obey Bucket Fill Number 1. Description : Each RMS bucket may have a fill number specified when the file is created. Since the PRM user cannot specify the value of this parameter during PRMCre, this feature is only valid when opening an existing file created with RMSDEF or RMSDFN. 2. Default : Fill the bucket as much as possible. 10. MassInsert - Mass Insert records 1. Description : Used for RMS indexed files only. Normally RMS will traverse the indexed tree with each record insert. If this option is selected, the record is placed in the file at the present pointer location. Extreme caution should be exercised when using this option. Refer to the RMS MACRO-11 Reference Manual for details. 2. Default : No mass insert 11. FileEnd - File Pointer to End-Of-File 1. Description : When opening an existing RMS Sequential file this option can be used. The option will position the file pointer to the end of the file in preparation for the addition of records to the file. 2. Default : File pointer to the beginning of the file.  Pascal Record Management User's Manual Page 3-4  Detailed Description of PRM Buffers 12. RecForm - Logical Record Format 1. Description : The record format of fixed length, variable length or stream format records. Specify FFIX for a fixed length record, FVAR for a variable length record and FSTREAM (sequential file only) for stream format. 2. Default : Fixed 13. Allocation - File Block Initial Allocation 1. Description : The number of disk blocks that should be initially allocated to the file during file creation. 2. Default : 0 blocks 14. BucketSize - RMS Bucket Size 1. Description : A logical unit of storage for RMS files is known as the bucket. Specify the number of blocks for each bucket. 2. Default : 1 15. EXTQUA - Default Extension Quatity 1. Description : If the file is dynamically extended, this number specifies the number of blocks the file will be extended. Should always be specified to avoid file header entries and hence file access performance degradation. 2. Default : 1 block extended 16. Contiguous - Contiguous File 1. Description : The file size specified by the allocation field is allocated in contigous disk blocks. If the contigous blocks are not available, an error is returned. 2. Default : Non-contiguous 17. Temporary - Temporary File 1. Description : The file will be deleted  Pascal Record Management User's Manual Page 3-5  Detailed Description of PRM Buffers automatically by the operating system when the file is closed. The file is in existence only while the file is open. 2. Default : Permanent File 3.2 RetRecord - Record Retrieval The following record fields contain data that interact. It is important that ALL the required fields be loaded to satify the record organization and record access. The following gives a description of the fields in the PRM retrieval buffer RetRecord: 1. KEYNUM - Key Number 1. Indexed Key : If the Search Type (defined below) is EQ, GT or GE then this entry is the Indexed key number that RMS is to use for data record retrieval. This number can be 0 (primary key) to n-1 where n is the number of keys in the indexed file. 2. RFA : If the Search Type (defined below) is RFA then the Key Number is the RFA number. Any file organization can use this type of access. Sequential files can use random access if using RFA access. Refer to paragraph 1.4 for details. 3. Default : None 2. SEARCH - Mode of Record Search 1. EQ, GT, GE : Search types of EQ, GT or GE are for access of Indexed records only. These search types define the comparison criteria for retrieving records. The comparison is made between the data in the KEYDATA field of this buffer (defined below) and the contents of the file key data for the key specified in the KEYNUM (defined above) field. 2. RFA : The RFA search type can be for any file organization. The KEYNUM field must be loaded with the RFA number. 3. NEX : The NEX search type can be used to access  Pascal Record Management User's Manual Page 3-6  Detailed Description of PRM Buffers the NEXt record in the file. This mode is used to sequential access records from a Relative or Indexed file. This is the only record access for RMS Sequential files. This mode is used after positioning the record stream to a file position using a random access search. The random access search is executed using PrmRet witha GET or FIND operation. 4. REC : The REC search type specifies that the KEYDATA field (described below) is a record number of a Relative file type. 3. RECSIZE - Logical Record Size 1. Input : You must specify the size of the record you want retrieved prior to each PrmRet operation. Since the field is both an input and output, the record size loaded will be destroyed and therefore must be reloaded before each PRMRet call. RMS will transfer all or part of the record from the file. If you specify recsize < file record size, only part of the record will be transferred and the RMS error ERRTB will be returned. If you specify recsize > file record size, the record buffer will be partially filled with the record and PRM will load RECSIZE with the size of the record transferred to your record buffer. If you specify a record size > than the allocated buffer, PRM will assume the record size to be correct. The record will destroy data following the record buffer. Refer to paragraph 2.9.1 for details. 2. Output : The size of the record retrieved from the RMS file is loaded in this field and passed back to the calling program. This may be useful information when variable length records are used. 4. RFAOut - RFA output from PRM 1. Description : The RFA (Records File Address) generated by RMS is passed back to the calling program. For details on usage of RFA's refer to paragraph 1.4. refer to paragraph 1.4.  Pascal Record Management User's Manual Page 3-7  Detailed Description of PRM Buffers 5. KEYSIZE - Size of the key data 1. Description : Valid for indexed files only. If you want a generic search, specify the search type of EQ, GT or GE then specify a key size that is < the full key size of the specified key in KEYNUM. For example, if the key data is for zip codes and you want all records with zip codes that begin with 5501, load KEYDATA with 5501, search=EQ, KEYSIZE=4, execute a PRMRet and the first record in the file with 5501x will be returned. Switch to sequential access (NEX search type) and call PRMRet to access all the records within the generic zip code range. 2. Default : None 6. KEYDATA - String or Integer key data 1. Indexed : The string or integer value the PRMRet operation is searching for in the indexed file. RMS will search the file for a key according to the search mode specified in the Search field (above). 2. Relative : The relative record number of a RMS relative file. 3.3 StoRecord - Record Storage The storage type operations use the StoRecord type buffer. The following describes the StoRecord fields: 1. RecSize - Record Size 1. Description : The size of the data record you want stored in the RMS file. You can specify a record size <= to full record size for files with variable record formats. If you specify a record size > the allocated record buffer, data that is not part of the logical record (garbage following the record buffer) will be assumed as part of the record. The record stored in the file will be corrupted. 2. Default : None  Pascal Record Management User's Manual Page 3-8  Detailed Description of PRM Buffers 2. RFAOut - The RFA generated by RMS-11 when the record was stored in the file. The RFA can be stored internally or in a file. The RFA can then be used to access the record if the file has not be reorganized. 3. KEY - RELATIVE Files only, The relative record number of the target cell for the record to be stored. 3.4 IdxKeyDesc - Indexed Key Description This buffer is used to define the keys of a dynamically created indexed file. The buffer is loaded and PRMKey routine is called to describe each key of the file being created. The keys must be defined in ascending order. The following describes the fields of the record type IdxKeyDesc: 1. KeyNum - Indexed Key Number 1. Description : The indexed key number that the record describes. This can be any number from 0-255. 2. Default : None 2. KeyPos - Key Position in the Record 1. Description : The starting byte position (start with 0) of the key in the logical record. 2. Default : None 3. KeySiz - Size of the Key 1. Description : Size in bytes of the key defined. 2. Default : None 4. KeyTyp - Key Type 1. Description : The key can be of type string or integer. Other types of keys are available but not supported by PRM. 2. Default : String  Pascal Record Management User's Manual Page 3-9  Detailed Description of PRM Buffers 5. KEYDUP - Duplicate Key 1. Description : If the key being defined allows duplicate entries, specify a "Y" in this field. 2. Default : No Duplicates 6. KEYCHG - Key value change 1. Description : Valid for alternate keys only. If selected the value of the key may be altered on a record update. 2. Default : No Changes 7. KeyNul - Key Null value 1. Description : Valid for alternate keys only. If a keyed field of the record is not valid for all records in the file, a null key value can be specified. If a null key value is defined and the field if FILLED with the null key value during a record insert (PRMSto - PUT) there will be no entry in the alternate key structure. Example: A file has a key in an employees record describing the name of the company softball ball team the employee belongs to. A null key value should be specified so that unneccessary entries in the tree structure for the alternate key are not entered for employees that do not belong to a team. 2. Default : No Null 3.5 User Defined Record Buffers The RecDef Record TYPE has to be modified to define the fields of your logical record. Multiple CASE entries can be used to define all the logical records. Once the buffer is defined, one or more record buffers should be allocated in the user space. Refer to paragraph 2.3 for more detail. CHAPTER 4  Detailed Description of PRM Routines This chapter describes the PRM calls used to interpret the User's request and pass the request to RMS-11. 4.1 General Use To use any of the PRM calls, the user must properly prepare the task with the proper buffer types and external calls. The following list the coding rules to follow for PRM calls: 1. The RMSIni routine must be executed before any other PRM routine is called. 2. The calling routines must be OMSI Pascal V1. If Pascal V2.0 is used, the version 1 switch must be used on the external call. Pascal V1.2H code has not been tested. If used, specify the contents of all fields rather than taking the defaults. 3. Once a file has been opened, file work space is allocated in the buffer of TYPE RmsFileDesc you provide on the open. This buffer is used for all file operations on that file. 4. A variable of TYPE RMSStatus word should be checked after ALL PRM calls. The value of +1 will indicate success, a negative value will indicate failure. The negative value can be a PRM error or an RMS type error. If an RMS error, word 1 of the status will be loaded with the RMS STS and word 2 with the RMS STV value. Definition of these errors can be found in the RMS User or RMS Macro Reference Manuals. The PRM returned error codes are defined in the CONST section of PRMPrefix.Pas and Appendix D.  Pascal Record Management User's Manual Page 4-2  Detailed Description of PRM Routines 5. Do not perform any record operations unless the file has been properly opened and initialized. If PRM routines (PRMOpe or PRMCre) do not successfully open the RMS file all PRM record operations will be inhibited and error code PrIni will be returned in word 1 of the status. If PRM allows record operations on an inproperly opened file, unpredictable results could occur. 6. If the RmsFileDesc buffer is used for multiple files, care must be used. When using the buffer for multiple files, be sure to close the file before re-use. When the buffer is available, reload the buffer with the new parameters describing the file. 4.2 File Access and Creation The following paragraphs describe the PRM routines that are used to open or create RMS-11 files. All file types are supported for both the access to existing files and creation of new files. The following describes the requirements for the use of each file type external procedure and possible errors that can occur from their use. Detail on each of the File Operations for each file organization is located in the RMS-11 User's Guide. 4.2.1 PrmClo This procedure is used to close an open RMS file. The RMSFileDesc type buffer passed to the procedure specifies the file to be closed. The RMS Sts and Stv values are passed backed to the calling program. These values should be checked to insure the close was successful. 4.2.2 PrmCre This procedure is used to dynamically create an RMS file. All file organizations can be created by simply defining the file type you want created and loading the remaining file creation fields in the RMSFileDesc record. For creation of an indexed file, the PRMKey routine must be called at least one time (define primary key) before calling the PRMCre routine.  Pascal Record Management User's Manual Page 4-3  Detailed Description of PRM Routines 4.2.3 PrmKey This call is used when you desire to create an RMS indexed file. Call PrmKey to define each key of the indexed file prior to the PrmCre call. PrmKey can be called multiple times defining a new key with each call. The keys are defined in a buffer of type IdxKeyDesc. When defining more than one key, define the keys in ascending order starting with the primary key (key 0). RMS will generate an error on the create if you do not follow this convention. 4.2.4 PrmOpe This procedure will open an exising RMS type file. The file can be previously defined with an RMS utility (RMSDef or RMSDfn) or by any other program that has created the RMS-11 file. When the file is opened, PRM FATAL conditions may be detected. The error is the result of not following PRM conventions. The error code is returned in the PrmStatus. A description of these error codes is described in Appendix D. These types of errors should be corrected immediately. If PrmOpe does not properly initialize, ALL record operations on the file will be rejected by PRM record operations. This feature is for the user that ignores the error codes returned from PrmOpe. If the file is not properly opened and record operations are performed, the task may abort with ODD ADDRESS (or other) type fatal errors. A recordsize specified in the RmsFileDesc buffer <> file record size is considered improper initialization. 4.3 Record Access and Storage The following describes all record operations supported by PRM. The record operations are described here in terms of the PRM interface. Detailed information describing the record operation for each file organization can be located in the RMS-11 User's Manual.  Pascal Record Management User's Manual Page 4-4  Detailed Description of PRM Routines 4.3.1 PrmDel This procedure is used to delete a record previously located with a SUCCESSFUL PrmRet PGET or PFIND operation. The user should make sure that the file pointer is properly positioned before calling this procedure. That is, the user must check the PrmStatus code returned from the PrmRet operation for a success code (+1) before calling PrmDel. 4.3.2 PrmFre This procedure is used to unlock a bucket so other tasks can access records in the bucket. Buckets are locked only if the file is opened with ACCESS of PWRITE or PBOTH. The Access field default of Read only should be selected if your application is only going to read data. The PREAD file access will not lock buckets. If you specify a write or read/write access, the RMS bucket will be locked when you access records in the bucket of the file. The lock will remain on the bucket until 1) your application accesses another record not in the presently locked bucket, 2) your application closes the file or 3) your application executes the PrmFre call. If your application is updating or writing records in a shared file, this call should be kept in mind. The call is especially useful when dealing with interactive type programs. The operator response should be timed if the application is holding a bucket locked and the continuation of the program is dependant on the operator (who may have just gone on a coffee break). 4.3.3 PrmRet This call is used to retrieve a record from a properly opened RMS file. Before access to the RMS file is attempted, a check is made to see if PrmOpe has been called and has properly opened the file. If the file has not been opened properly, a FATAL message will be printed and the RMSRet operation will not be performed. Load the RetRecord buffer prior to using this call. With the call, specify a PGET or PFIND record operation. Refer to the RMS-11 User's Guide for detail concerning GET and FIND record operations.  Pascal Record Management User's Manual Page 4-5  Detailed Description of PRM Routines 4.3.4 PrmSto This procedure is used to store a record in a file that has been properly opened with PrmOpe or PrmCre. The PrmSto Call defines the type of operation with the first parameter. If the PrmSto describes an PUPDATE, the store must be preceded by a successful PRMRet operation. If you define a PPUT operation, the record in stored in a new location in the RMS file. Refer to the RMS-11 User's Guide for detail concerning the PUT and UPDATE record opeations. APPENDIX A  PRM Program Example - Access to existing files PROGRAM PrmExample ; { AUTHOR : Ken Tibesar ES and T Labs - Bldg. 518-1 3M Company St. Paul SYSTEM REQUIREMENTS: RSX-11M+ OPERATING SYSTEM OMSI V1.2G PASCAL COMPILER RMS-11 RECORD MANAGEMENT WITH PRM (Pascal Record Management created by 3M) BUILD PROCEDURE : Refer to Appendix C PROGRAM DESCRIPTION: This program shows access to the three types of RMS files. The files are created before the program executes. The program shows the following: 1. Open of an existing file. 2. Adding records to each file type. 3. Transferring records from seq. file to idx file. 4. Access to seq. file by RFA. 5. Access to rel. file. 6. Close the files. } CONST IdxLch = 3 ; { of the first 6 UNITS } RelLch = 4 ; { ch. 3 4 avail. by default } _ SeqLch = 7 ; { must spec. UNITS=n for units > 6 } NameSize = 30 ; { size of the file name } ExaRecSize = 28 ; { full record size } TYPE RecDef = RECORD { user defined record type 1 }  PRM Program Example - Access to existing files Page A-2 SecNum : ARRAY [1..4] OF CHAR ;{ section number } SecSup : ARRAY [1..3] OF CHAR ;{ sup initials } Fill : char ; SecDesc : ARRAY [1..20] OF CHAR END ; { RECORD } TwoWord = ARRAY [1..2] OF integer ; { record number size } KeyDef = RECORD CASE integer OF 1 : ( Idx0 : ARRAY [1..Key0Size] OF CHAR) ; 2 : ( Idx1 : ARRAY [1..Key1Size] OF CHAR) ; 3 : ( RecNum : TwoWord ) ; { REL file rec. } END ; {**************************************************************** BEGIN PRM CONST and TYPE file: PrmPrefix.Pas **************************************************************** } CONST { * Error values returned in status word 1 and word 2. * All errors set Status[1] to a negative value. * Refer to Appendix B of RMS User's Guide or App. D of this document. } PrINI = -5001 ; PrRNE = -5002 ; PrRsz = -5003 ; PrKY0 = -5004 ; PrKNS = -5005 ; PrAsc = -5006 ; ErDup = -544 ; ErEof = -592 ; ErFac = -656 ; ErFnf = -736 ; ErRlk = -1440 ; ErRnf = -1472 ; TYPE RmsFileName = ARRAY [1..NameSize] OF CHAR ; RmsStatus = ARRAY [1..2] OF integer ; OrgTypes = (SEQ,REL,IDX) ; AllowTypes = (Share,NoShare) ; AccessTypes = (PRead,PWrite,PBoth) ; FormType = (FFIX,FVAR,FSTREAM) ;{ record format type } RmsFileDesc = RECORD Org : OrgTypes ; { spec. file type } FileName : RmsFileName ; LogChan : integer ; { spec. ch. n }  PRM Program Example - Access to existing files Page A-3 Allow : AllowTypes ; { what others may do } Access : AccessTypes ; { what you may do } RecordSize : INTEGER ; { full rec. size } Windows : INTEGER ; { no. of ret. windows } { enable options with a capital "Y" } DeferWrite : CHAR ;{ IDX, defer write } Unlock : CHAR ;{ REL IDX, don't lock } _ ObeyFill : CHAR ;{ obey bucket fill no. } MassInsert : CHAR ;{ ref. rms-11 ref. man. } FileEnd : CHAR ;{ SEQ only, place at end } { file creation fields } RecForm : FormType ; { rec. format } Allocation : TwoWord ; { no. blocks allocated } BucketSize : integer ; { data bucket size } ExtQua : integer ; { no. blks extend file } { Enable following with capital "Y", if not loaded, } Contiguous : CHAR ; { create contiguous file } Temporary : char ; { delete file when closed } WorkSpace : PACKED ARRAY [1..160] OF char ; END ; { RmsFileDesc Record } SearchTypes = (EQ,GT,GE,RFA,NEX,REC) ; ThreeWord = ARRAY [1..3] OF Integer ;{ for RFA's } RecOps = (PGET,PFIND,PPUT,PUPDATE) ; RetRecord = RECORD { - USE with PRMRET, INPUT - to GET and FIND } KeyNum : Threeword ; { INPUT- IDX Key or RFA } Search : SearchTypes ; { INPUT - spec. search opr } RecSize : integer ; { INPUT - sz rec. to PGET OUTPUT- sz rec. returned } RFAout : ThreeWord ; { OUTPUT- valid if <> RFA } KeySize : integer ; { INPUT - size of key data } KeyData : KeyDef ; { INPUT - key string or rec. } END ; { RetRecord RECORD Definition } StoRecord = RECORD { USE with PRMSTO, Input to PUT and UPDATE } RecSize : integer ; { INPUT - spec. rec. buffer } RFAOut : ThreeWord ; { OUTPUT - record rfa } Cell : KeyDef ; { INPUT - REL cell no. } END ; { StoRecord Record } {***************************************************** * END PRM CONST and TYPE * *******************************************************} VAR chtfile : text ;  PRM Program Example - Access to existing files Page A-4 Rlen : integer ; i : integer ; SeqRfas : ARRAY [1..4] OF ThreeWord; IdxFile : RmsFileDesc ; { file parameters } IdxStoBuf : StoRecord ; { store buffer } RelFile : RmsFileDesc ; { file parameters } SeqFile : RmsFileDesc ; { file parameters } SeqStoBuf : StoRecord ; { buf sequential file } RecBuf : RecDef ; { same record buffer all files } RetBuf : RetRecord ; { retreival buf for all file } RfaBuf : Threeword ; { returned rfa } Status : RmsStatus ; { rms status codes } { close the file } PROCEDURE PRMClo ( VAR Filebuf : RmsFileDesc ; VAR Status : RmsStatus ) ; { STS and STV } EXTERNAL ; { Delete a record } PROCEDURE PRMDel ( VAR FileBuf : RmsFileDesc ; VAR Status : RmsStatus ) ; { STS and STV } EXTERNAL ; { Open an RMS Indexed file previously defined with RMSDEF } PROCEDURE PRMOpe ( VAR FileBuf : RmsFileDesc ; VAR Status : RmsStatus ) ; { Sts and Stv } EXTERNAL ; { Record retrieval from the specified file } PROCEDURE PRMRet( Operation : RecOps ; VAR FileBuf : RmsFileDesc ; VAR RetData : RetRecord ; VAR RecBuf : RecDef ; VAR Status : RmsStatus ) ; EXTERNAL ; { Store a record in the specified file } PROCEDURE PRMSto ( Operation : RecOps ; VAR FileBuf : RmsFileDesc ; VAR StoData : StoRecord ; VAR RecBuf : RecDef ; VAR Status : RmsStatus); EXTERNAL ; PROCEDURE RmsIni ; EXTERNAL ; PROCEDURE OpenFiles ;  PRM Program Example - Access to existing files Page A-5 BEGIN { open an rms indexed file } WITH IdxFile DO BEGIN Org := IDX ; FileName := '[300,47]PrmExa.Idx ' ; LogChan := IdxLch ; Access := PBoth ; RecordSize := ExaRecSize ; END ; { all fields not specified will take their default condition } PrmOpe ( IdxFile, Status ) ; IF Status[1] < 1 THEN writeln('Idx Open error, code=',Status[1], Status[2] ) ; { open and rms relative file } WITH RelFile DO BEGIN Org := REL ; FileName := '[300,47]PrmExa.Rel ' ; LogChan := RelLch ; Access := PBoth ; RecordSize := ExaRecSize ; END ; PrmOpe ( RelFile, Status ) ; IF Status[1] < 1 THEN writeln('Rel Open error, code=',Status[1], Status[2] ) ; { open an rms sequential file } WITH SeqFile DO BEGIN Org := SEQ ; FileName := '[300,47]PrmExa.Seq ' ; LogChan := SeqLch ; Access := PBoth ; SeqFile.FileEnd := 'Y' ; RecordSize := ExaRecSize ; END ; PrmOpe ( SeqFile, Status ) ; IF Status[1] < 1 THEN writeln('Seq Open error, code=',Status[1], Status[2] ) ; END ; { PROCEDURE Openfiles } PROCEDURE AddNewRec ( VAR TarFile : RmsFileDesc ; VAR TarRec : RecDef ; VAR TarStoBuf : StoRecord ) ; PROCEDURE StoreIt ; BEGIN TarStoBuf.RecSize := ExaRecSize ; { specify each time } PRMSto ( PPUT, TarFile, TarStoBuf, RecBuf, Status ) ;  PRM Program Example - Access to existing files Page A-6 writeln('store ', status[1],status[2]); END ; BEGIN TarStoBuf.RecSize := ExaRecSize ; { load the record buffer } TarRec.SecNum := '86A ' ; TarRec.SecSup := 'AAC' ; TarRec.SecDesc := 'Optical Inspection ' ; StoreIt ; TarRec.SecNum := '86C ' ; TarRec.SecSup := 'TMT' ; TarRec.SecDesc := 'Ultrasonic Process ' ; StoreIt ; TarRec.SecNum := '86B ' ; TarRec.SecSup := 'WHO' ; TarRec.SecDesc := 'Computer Nurds ' ; StoreIt ; END ; { PROCEDURE AddNewRec } PROCEDURE XferToSeq ; BEGIN { find the first record by retreiving with a search of GE and setting a key value < the first record key entry of the file } RetBuf.KeyNum[1] := 0 ; { load IDX key } RetBuf.Search := GE ; { set search type } RetBuf.KeySize := 1 ; { size of key data } RetBuf.KeyData.Idx0 := ' ' ; { set the key=blanks } RetBuf.RecSize := ExaRecSize ; { load each time } PrmRet ( PFIND, IdxFile, RetBuf, RecBuf, Status ) ; IF Status[1] < 1 THEN writeln('idx retreive error=',status[1], status[2]) ELSE BEGIN writeln ; writeln('begin xfer'); i := 1 ; RetBuf.Search := NEX ; { set sequential mode } REPEAT RetBuf.RecSize := ExaRecSize ; { load each time } PrmRet( PGET, IdxFile, RetBuf, RecBuf, Status ) ; IF Status[1] < 1 THEN writeln('GET fail = ',status[1],status[2] ) ELSE BEGIN RetBuf.RecSize := ExaRecSize ; { load each time } PRMSto ( PPUT, SeqFile, SeqStoBuf, RecBuf, Status ) ; IF Status[1] < 1  PRM Program Example - Access to existing files Page A-7 THEN writeln('PUT fail = ',status[1],status[2] ) ELSE IF i < 5 THEN BEGIN SeqRfas[i,1] := SeqStoBuf.RfaOut[1] ; SeqRfas[i,2] := SeqStoBuf.RfaOut[2] ; SeqRfas[i,3] := SeqStoBuf.RfaOut[3] ; writeln('Stored at RFA=', SeqRfas[i,1]:4, SeqRfas[i,2]:4,SeqRfas[i,3]:4, ' data=', RecBuf.SecNum, RecBuf.SecSup, recBuf.SecDesc ) ; i := i + 1 ; END ; END ; UNTIL Status[1] = ErEof ; writeln('xfer from idx to seq complete') ; END ; { ELSE } END; { PROCEDURE XferToSeq } PROCEDURE RetByRfa ; PROCEDURE GetRecord ( i : integer ) ; BEGIN RetBuf.KeyNum[1] := SeqRfas[i,1] ; RetBuf.KeyNum[2] := SeqRfas[i,2] ; RetBuf.KeyNum[3] := SeqRfas[i,3] ; RetBuf.RecSize := ExaRecSize ; { load each time } PrmRet( PGET, SeqFile, RetBuf, RecBuf, Status ) ; IF Status[1] >= 1 THEN { write the record } writeln('RFA NO.= ', SeqRfas[i,1]:4, SeqRfas[i,2]:4, SeqRfas[i,3]:3,' data=', RecBuf.SecNum, RecBuf.SecSup, recBuf.SecDesc ) ELSE writeln('RFA access error=',status[1],status[2]) ; END ; BEGIN writeln; writeln('Begin random retreival from a seq. file by RFA') ; RetBuf.RecSize := ExaRecSize ; RetBuf.Search := RFA ; { set search to access by RFA } GetRecord ( 4 ) ; { get record spec. in array [4] } GetRecord ( 1 ) ; GetRecord ( 3 ) ; GetRecord ( 2 ) ; END; { PROCEDURE RetByRfa } PROCEDURE RetRelative ; BEGIN RetBuf.KeyData.RecNum[1] := 1 ; { specify record no. } RetBuf.KeyData.RecNum[2] := 0 ; RetBuf.Search := REC ; { search by a rec }  PRM Program Example - Access to existing files Page A-8 RetBuf.RecSize := ExaRecSize ; PrmRet( PFIND, RelFile, RetBuf, RecBuf, Status ) ; IF Status[1] < 1 THEN writeln (' fail to find 1st relative record, sts=',status[1] ) ; RetBuf.Search := NEX ; { switch from random to seq search } writeln; writeln('Begin Relative File data retreival') ; IF Status[1] >= 1 THEN REPEAT { dump the entire file contents } PrmRet( PGET, RelFile, RetBuf, RecBuf, Status ) ; IF Status[1] >= 1 THEN writeln('data = ', RecBuf.SecNum, RecBuf.SecDesc ) ELSE writeln('Get error=',status[1], status[2]); UNTIL Status[1] = ErEof ; END ; BEGIN RmsIni ; { must specify before any rms ops } Openfiles ; { open all the files } AddNewRec ( IdxFile, RecBuf, IdxStoBuf ) ; AddNewRec ( RelFile, RecBuf, IdxStoBuf ) ; AddNewRec ( SeqFile, RecBuf, SeqStoBuf ) ; XferToSeq { transfer records from idex to seq. file } RetByRfa ; { retrieve random from seq. by RFA } RetRelative ; { retrieve all records from relative file } PrmClo ( IdxFile ,status) ; { close all the files } PrmClo ( RelFile ,status) ; PrmClo ( SeqFile ,status) ; END. APPENDIX B  PRM Example of Creating an RMS Indexed File PROGRAM CREIDX ; { AUTHOR : Ken Tibesar ES and T Labs - Bldg. 518-1 3M Company St. Paul SYSTEM REQUIREMENTS: RSX-11M+ OPERATING SYSTEM OMSI V1.2G PASCAL COMPILER RMS-11 RECORD MANAGEMENT WITH PRM (Pascal Record Management created by 3M) BUILD PROCEDURE : Refer to Appendix C PROGRAM DESCRIPTION : This program is an example of dynamic definition and creation of an RMS Indexed File. The program defines 4 keys of an indexed file, stores 1 record and closes the file. Status codes are displayed after each PRM call. } CONST NameSize = 30 ; { sz of input file name, do not alter } TYPE { The record buffer used for this example has two uses. The code in the program below uses only CASE 1 fields, CASE 2 is included as an example only. } RecDef = RECORD { user defines field names and sizes } CASE integer OF 1 : (Dat1 : ARRAY [1..10] OF CHAR ; Dat2 : integer ) ; 2 : (Item1 : ARRAY [1..36] OF CHAR ; Item2 : REAL ) ; END ; { User Defined Record } TwoWord = ARRAY [1..2] OF integer ; { record number size }  PRM Example of Creating an RMS Indexed File Page B-2 KeyDef = RECORD CASE integer OF 1 : ( KeyX : ARRAY [1..KeyXSize] OF CHAR) ; 2 : ( KeyY : ARRAY [1..KeyYSize] OF CHAR) ; 3 : ( RNum : TwoWord ) ; { relative record cell no. } END ; RmsFileName = ARRAY [1..NameSize] OF CHAR ; RmsStatus = ARRAY [1..2] OF integer ; OrgTypes = (SEQ,REL,IDX) ; AllowTypes = (Share,NoShare) ; { what others can do } AccessTypes = (PBoth,PRead,PWrite) ; { what you can do } FormType = (FFIX,FVAR,FSTREAM) ; { record format type } RmsFileDesc = RECORD { -- Use with PRMOPE to define an existing file to be opened -- } Org : OrgTypes ; { spec. file type, no default } FileName : RmsFileName ; { full spec. of rms file } LogChan : integer ; { spec. ch. n, no def. } Allow : AllowTypes ; { what others may do } Access : AccessTypes ; { what you may do } RecordSize : INTEGER ; { spec. max. file rec. sz } Windows : INTEGER ; { no. of ret. windows } { enable the following options with a capital "Y" } DeferWrite : CHAR ; { IDX, defer write } Unlock : CHAR ; { unlock if locked } ObeyFill : CHAR ; { obey bucket fill numbers } MassInsert : CHAR ; { ref. rms-11 ref. man. } FileEnd : CHAR ; { SEQ only, stream to EOF } { file creation fields } RecForm : FormType ; { rec. format } Allocation : TwoWord ; { no. blocks allocated to file } BucketSize : integer ; { data bucket size } ExtQua : integer ; { no. blks dynamic extend file } { Enable following with capital "Y" } Contiguous : CHAR ; { create a contiguous file } Temporary : char ; { delete the file when closed } workspace : Array [1..160] of char ; END ; { RmsFileDesc Record } SearchTypes = (EQ,GT,GE,RFA,NEX,REC) ; ThreeWord = ARRAY [1..3] OF Integer ; { for RFA's } RecOps = (GET,FIND,PUT,UPDATE) ; StoRecord = RECORD { USE with PRMSTO, Input to PUT and UPDATE } RecSize : integer ; { INPUT - spec. rec. buffer data to be stored }  PRM Example of Creating an RMS Indexed File Page B-3 RFAOut : ThreeWord ; { OUTPUT - record RFA } Key : KeyDef ; { INPUT - REL ONLY, rec. } END ; { StoRecord Record } KType = (StrKey,IntKey) ; { string or unsigned integer } IdxKeyDesc = RECORD { used with prmkey to define keys } { use prior to PrmCre of an indexed file type } KeyNum : Integer ; { key of ref. } KeyPos : Integer ; { byte position of key in rec. } KeySiz : Integer ; { size of the key defining } KeyTyp : KType ; { string or unsigned integer } KeyDup : char ; { 'Y' to allow duplicate keys } KeyChg : char ; { 'Y' for key changes, alt. only } KeyNul : char ; { null key value for alt. key } END ; { IdxKeyDesc } {************************************************************ END PRM CONST and TYPE *************************************************************} VAR FBuf : RmsFileDesc ; { file creation buffer } RBuf : RecDef ; { data record buffer } SBuf : Storecord ; { storage desc. buffer } KBuf : IdxKeyDesc ; { key description buffer } PrmStatus : RmsStatus ; { status for all calls } {********************************************************** * START PRM PROCEDURE CALLS * **********************************************************} { close the file } PROCEDURE PRMClo ( VAR Filebuf : RmsFileDesc ; VAR Status : RmsStatus ) ; { STS and STV } EXTERNAL ; PROCEDURE PrmCre ( VAR CreBuf : RmsFileDesc ; VAR Status : RmsStatus ) ; EXTERNAL ; { Define single key of indexed file, use in conj. with PrmCre } { Define keys in ascending order } PROCEDURE PRMKey (VAR Filebuf : RmsFileDesc ; VAR KeyBuf : IdxKeyDesc ; VAR Status : RmsStatus ) ;{ Sts and Stv } EXTERNAL ; { Store a record in the specified file } PROCEDURE PRMSto ( Operation : RecOps ; VAR FileBuf : RmsFileDesc ;  PRM Example of Creating an RMS Indexed File Page B-4 VAR StoData : StoRecord ; VAR RecBuf : RecDef ; VAR Status : RmsStatus); { STS and STV } EXTERNAL ; PROCEDURE RmsIni ; EXTERNAL ; {********************************************************* * BEGIN MAIN PROGRAM * *********************************************************} BEGIN RmsIni ; { required before any PRM call } { ***** BEGIN INDEXED KEY DEFINITIONS ***** } { linked list of XAB's created to define keys } WITH KBuf DO BEGIN KeyNum := 0 ; { KEY NUMBER 0, PRIMARY KEY } KeyPos := 0 ; KeySiz := 5 ; END ; PrmKey ( FBuf, KBuf, PrmStatus ) ; WITH KBuf DO BEGIN KeyNum := 1 ; { KEY NUMBER 1, ALTERNATE KEY } KeyPos := 3 ; KeySiz := 5 ; END ; PrmKey ( FBuf, KBuf, PrmStatus ) ; WITH KBuf DO BEGIN KeyNum := 2 ; { KEY NUMBER 2, ALTERNATE KEY } KeyPos := 4 ; KeySiz := 3 ; END ; PrmKey ( FBuf, KBuf, PrmStatus ) ; WITH KBuf DO BEGIN KeyNum := 3 ; { KEY NUMBER 3, ALTERNATE KEY } KeyPos := 8 ; KeySiz := 2 ; END ; PrmKey ( FBuf, KBuf, PrmStatus ) ; { ***** END INDEXED KEY DEFINITIONS ***** } { set-up the file parameters } WITH FBuf DO BEGIN Org := IDX ; { create an indexed file } FileName := 'cretst.IDX ' ; LogChan := 4 ; RecordSize := 30 ;  PRM Example of Creating an RMS Indexed File Page B-5 Allocation[1] := 10 ; { pre-allocate 10 blocks } Allocation[2] := 0 ; BucketSize := 2 ; Contiguous := 'Y' ; END ; { WITH FBuf } PrmCre ( FBuf, PrmStatus ) ; { create the indexed file } { DISPOSE of XAB's, return space to HEAP } writeln ( 'File created, sts=',prmstatus[1], ' stv=',prmstatus[2] ) ; { store a single record } RBuf.Dat1 := 'file data ' ; RBuf.Dat2 := 64 ; SBuf.RecSize := 12 ; PrmSto ( PUT, FBuf, SBuf, RBuf, PrmStatus ) ; writeln ( 'Store data, sts=',prmstatus[1], ' stv=',prmstatus[2] ) ; PrmClo ( FBuf, PrmStatus ) ; writeln ( 'File closed, sts=',prmstatus[1], ' stv=',prmstatus[2] ) ; END. APPENDIX C  Command and Overlay Description Files Six logical unit numbers are provided by default for each task. Logical channel numbers 3 and 4 are available to the PRM user. The other four are used by the system and Pascal. PRMExa requires 3 logical channel therefore UNITS=7 is specifed in the command file. File : PrmExaBld.Cmd PRMEXA/CP/FP,PRMEXA/-SP=PRMEXA/MP ; ; following possible only if RMS resident library is supported LIBR=RMSRES:RO:6 ; ; refer to OMSI Pascal manual for detail on the following EXTSCT=$$HEAP:4000 UNITS=7 ; ; refer to the task builder manual Options description for details File : PrmExa.Odl ; REFER to RMS User's manual for detail on overlay files .ROOT PRMEXA-RMS-PAS-RMSROT-RMSALL ; ; pascal interface to PRM routines RMS: .FCTR lb:[300,47]PRMPAS/LB ; ; pascal libray PAS: .FCTR lb:[300,41]PASLIB/LB ; ; DEC supplied overlay structure for resident library @lb:[300,45]RMSRLX.ODL .END APPENDIX D  PRM Error Codes PRM-11 loads the RMS-11 completion code in a two word buffer provided by the user for ALL PRM file and record operations. The code loaded is compatible with the MACRO-11 STS and STV error code values. Refer to Appendix B in the RMS-11 User's Guide for explantion of the RMS-11 error codes. If the PRM User incorrectly uses the PRM calls, PRM will generate an error code unique to the PRM interface. The error code will be passed to the user in the STS field of the standard two word buffer. To avoid collision with standard error codes, PRM error codes start at -5000. The following table gives a brief explanation of the cause of the error. Symbolic STS STV Description PrINI -5001 NA A record operation was attempted on a file that was not properly opened by PrmOpe or PrmKey. Check proper open or create of a file before continuing with record ops. PrRNE -5002 Lch An existing file was opened and the user program did not specify the correct file max. record size. The logical channel no. of the file attempting to open is in word 2. All record operations will be inhibited. Use rms utility RMSDSP to determine actual record size and correct user recordsize. PrRsz -5003 RecSz During a PrmRet call a record size must be specified so Prm knows the size of the record to be returned. The record size field is an input and output field therefore it must be loaded before EACH PrmRet. A  PRM Error Codes Page D-2 PrmRet rms failure will set the record size field to 0. The record size specified by the user is returned in word 2. PrKY0 -5004 NA During a PrmKey call the primary key must be specified first. PrKNS -5005 NA During a PrmCre call a indexed file organization was specified and no primary key defined. You must use PrmKey to define at least a primary key for indexed files. PrAsc -5006 NA Keys defined to PrmKey were defined in a non-ascending key order.