|
OpenVMS Record Management Services Reference
Manual
B.3.1 Creating, Accessing, and Deaccessing a File
The Create service constructs a new file according to the attributes
you specify in the FAB for the file, whereas the Open service makes an
existing file available for processing by your program.
Both of these services, invoked by the $CREATE and $OPEN macros
respectively,
allocate resources within the system to establish access (a path) to a
file. You must open or create a file to perform most file operations
and any record
operations on that file. Applications designed for shared access must
declare the type of sharing at this time. The user specifies the
various types of
shared access by setting bits in the file access control (FAB$B_FAC)
and share (FAB$B_SHR) fields in the appropriate FAB.
RMS provides several file-processing options for the Create service. The
create-if option (FAB$V_CIF option in the FAB$L_FOP field) requests
that the file be created only if it does not exist. If the file does
exist in the specified directory, the file is opened, not created. The
Open and Create services both establish access to the desired file, but
the Create service additionally allocates disk space and performs
functions related to allocation.
When you are finished processing a file, you invoke the Close service
($CLOSE macro) to close the file, disconnect all record streams
associated with the file, and free all resources allocated to the file.
If you do not explicitly invoke the Close service when the program
image exits, RMS attempts an implicit close. All resources associated
with open files are returned when the files are deaccessed at image
rundown time. However, process permanent files are not implicitly
closed when an image exits. These are special files that the current
CLI opens outside the context of a normal image.
B.3.2 Example of Opening and Creating Files
Example B-2 illustrates the use of the Open, Create, Connect, Get,
Put, and Close services to access and copy records from one file to
another. Note that the arguments to the $FAB and $RAB macros are listed
vertically on separate lines for ease in reading them. However, the
argument list must be contiguous and a common programming error is
omission of required delimiters and continuation characters when the
arguments are listed in this manner.
Example B-2 Use of the Create, Open, and
Close Services |
.TITLE COPYFILE
;
; This program copies the input file to the output file.
;
.PSECT DATA,WRT,NOEXE
INFAB: $FAB FNM = <INFILE:>,- ; Primary input file name
DNM = <.INV> ; Default input file type
INRAB: $RAB FAB = INFAB,- ; Pointer to FAB
ROP = RAH,- ; Read-ahead option
UBF = REC_BUFF,- ; Record buffer
USZ = REC_SIZE ; and size
OUTFAB: $FAB FNM = <OUTFILE:>,- ; Primary output file name
DNM = <.INV>,- ; Default output file name
FOP = CTG,- ; Make contiguous file
FAC = <PUT>,- ; Open for PUT operations
SHR = <NIL>,- ; Exclusive file access
MRS = REC_SIZE,- ; Maximum record size
RAT = CR ; Implied carriage control
OUTRAB: $RAB FAB = OUTFAB,- ; Pointer to FAB
ROP = WBH,- ; Write-behind option
RBF = REC_BUFF ; Output uses same buffer
; as input
;
REC_SIZE = 132 ; Maximum record size
REC_BUFF:
.BLKB REC_SIZE ; Record buffer
.PSECT CODE,NOWRT,EXE
;
; Initialization - Open input and output files and connect streams
;
.ENTRY COPYFILE,^M<R6> ; Save R6
$OPEN FAB=INFAB ; Open input file
BLBC R0,EXIT1 ; Quit on error
$CONNECT RAB=INRAB ; Connect to input
BLBC R0,EXIT2 ; Quit on error
MOVL INFAB+FAB$L_ALQ,- ; Set proper size for output
OUTFAB+FAB$L_ALQ
$CREATE FAB=OUTFAB ; Create output file
BLBC R0,EXIT3 ; Quit on error
$CONNECT RAB=OUTRAB ; Connect to output
BLBS R0,READ ; Branch to READ loop
BRB EXIT4 ; Trap error
EXIT1: MOVAL INFAB,R6 ; Error: Keep FAB address
BRB F_ERR ; Signal file error
EXIT2: MOVAL INRAB,R6 ; Keep RAB address
BRB R_ERR ; Signal record error
EXIT3: MOVAL OUTFAB,R6 ; Keep FAB address
BRB F_ERR ; Signal record error
EXIT4: MOVAL OUTRAB,R6 ; If error, retain RAB addr.
BRB R_ERR ; Signal record error
;
; Copy records loop
;
READ: $GET RAB=INRAB ; Get a record
BLBS R0,WRITE ; Write the record
CMPL R0,#RMS$_EOF ; Was error end-of-file?
BEQL DONE ; Successful completion
BRB EXIT2 ; Error otherwise
WRITE: MOVW INRAB+RAB$W_RSZ, - ; Input RAB sets record
OUTRAB+RAB$W_RSZ ; size for output RAB
$PUT RAB=OUTRAB ; Write the record
BLBC R0,EXIT4 ; Quit on error
BRB READ ; Go back for more
;
; Close files, signal any errors, and exit
;
F_ERR: PUSHL FAB$L_STV(R6) ; Push STV and STS of FAB
PUSHL FAB$L_STS(R6) ; on the stack
CALLS #2, G^LIB$SIGNAL ; Signal error
BRB EXIT
R_ERR: PUSHL RAB$L_STV(R6) ; Push STV and STS of RAB
PUSHL RAB$L_STS(R6) ; on the stack
CALLS #2, G^LIB$SIGNAL ; Signal error
DONE: $CLOSE FAB=INFAB ; Close input
$CLOSE FAB=OUTFAB ; and output
EXIT: RET ; Return with status in R0
.END COPYFILE
|
This example illustrates how you can use the sequential file
organization to create a new file by copying records from an existing
file. The newly created file and the source file have variable-length
records.
This example assumes that an external program has identified the input
file as a search list logical name using this statement:
$ ASSIGN [INV]30JUN85,[INV.OLD]30JUN85 INFILE:
|
This directs RMS to look for the input file in directory [INV] first,
and if it does not find the file, it should look in directory [INV.OLD].
The program also specifies the default file type .INV for the input
file using this statement:
DNM=<.INV> ; Default input file name
|
Next the program configures the RAB used for the input file (labeled
INRAB). The first argument links the RAB to the associated FAB (INFAB)
and this is the only required argument to a RAB. The rest of the
arguments specify the read-ahead option (described in later text) and
the record buffer for the input file. The Get service uses the user
record buffer address (UBF) field and the user record buffer size (USZ)
field as inputs to specify the record buffer and the record size,
respectively.
Note
When you invoke the Get service, RMS takes control of the record buffer
and may modify it. RMS returns the record size and only guarantees the
contents from where it accessed the record to the completion of the
record.
|
The program then configures the FAB for the output file. The first
argument uses the FNM field to equate the file name to the externally
defined logical name OUTFILE. After the program specifies the default
file specification extension for the output file, it specifies three
additional FAB fields.
First it directs RMS to allocate contiguous space for the output file
by setting the CTG bit in the FAB$L_FOP field of the FAB.
Next the program uses a program-defined variable to store the value 132
in the MRS field:
MRS=REC_SIZE
REC_SIZE= 132
|
The program then specifies that each record is to be preceded by a line
feed and followed by a carriage return whenever the record is output to
a line printer or terminal:
Because the program alternately reads and then writes each record, the
input file and the output file may share the same buffer. However,
because the Put service does not have access to the UBF and UBZ fields,
the output RAB defines the buffer using the RBF and the RSZ fields.
Note that the UBF, USZ, and RBF values are set prior to run time, but
that the RSZ value is set at run time, just prior to invocation of the
Put service. This is done because the input file contains
variable-length records and the Put service relies on the Get service
to supply each record's size by way of the RSZ field, an INRAB output
field.
The following statement from the sample program illustrates this
feature:
WRITE: MOVW INRAB+RAB$W_RSZ, - ; Input RAB sets record
OUTRAB+RAB$W_RSZ ; size for output RAB
|
The run-time processing macros for the input file consist of a $OPEN, a
$CONNECT, a $GET, and a $CLOSE macro. Because the input file already
exists, the program accesses it with a $OPEN macro. The sole argument
to this macro identifies the FAB to the Open service:
Next, the program connects a record stream to the input file by calling
the Connect service and specifying INRAB as the appropriate RAB:
Note that upon completion of each service call, the program tests the
condition value in R0 returned by the service before proceeding to the
next call. If the call fails, the program exits with the appropriate
control block address in R6.
After creating the output file and establishing its record stream, the
program begins a processing loop in which the Get service reads a
record from the input file and the Put service writes the record to the
output file. When all file records are copied, as indicated by the
detection of the end of the file, the program exits to label DONE,
which closes both files.
The Close service disconnects the record stream for all RABs connected
to the specified FAB. In a multistream environment (more than one RAB
can be connected to a single FAB), a program may disconnect individual
record streams using the Disconnect service.
B.3.3 Example of Creating a Multiple-Key Indexed File
Example B-3 creates an indexed file on a remote node from a
sequential file on the local node. The indexed file contains three
keys: a segmented primary key and two simple alternate keys. The
segmented primary key includes the customer's last name, the first
letter of the customer's first name, and the customer's middle initial.
Example B-3 Use of the Create Service for an
Indexed File |
.TITLE CREATEIDX - CREATE INDEXED FILE
.IDENT /V001/
;
; This program creates an indexed file with three keys from a
; sequential file containing a name and address list. The record
; format of the input file is shown below:
;
; First Name Column 00-10
; Middle Initial Column 11-11
; Last Name Column 12-26
; Street Column 27-46
; City Column 47-58
; State Column 59-60
; Zip Code Column 61-65
; Reserved for
; new data Column 66-end of record
;
; The input and output files are specified by the logical names SRC
; and DST, respectively. For example:
;
; $ DEFINE SRC DBB1:[TEST]INPUT.DAT
; $ DEFINE DST TRNTO::DRA4:[RMS.FILES]OUTPUT.DAT
; $ RUN CREATEIDX
;
;********************************************************************
.SBTTL Control block and buffer storage
.PSECT DATA NOEXE,LONG
;
; Define the source file FAB and RAB control blocks.
;
SRC_FAB:
$FAB FAC=<GET>,- ; File access for GET only
FOP=<SQO>,- ; DAP file transfer mode
FNM=<SRC:> ; Name of input file
SRC_RAB:
$RAB FAB=SRC_FAB,- ; Address of associated FAB
RAC=SEQ,- ; Sequential record access
UBF=BUFFER,- ; Buffer address
USZ=BUFFER_SIZE ; Buffer size
;
; Define the destination file FAB and RAB control blocks.
;
DST_FAB:
$FAB FAC=<PUT>,- ; File access for PUT only
FOP=CTG,- ; Allocate contiguous
SHR = <NIL>,- ; Exclusive file access
FNM=<DST:>,- ; Name of output file
MRS=128,- ; Maximum record size
RFM=VAR,- ; Variable length records
RAT=<CR>,- ; Implied carriage control
ORG=IDX,- ; Indexed file organization
XAB=DST_KEY0 ; Address of start of XAB chain
DST_RAB:
$RAB FAB=DST_FAB,- ; Address of associated FAB
MBF=3,- ; Use 3 buffers
RAC=KEY,- ; Random record writes
RBF=BUFFER,- ; Buffer address
ROP=LOA,- ; Specify initial fill size
RSZ=BUFFER_SIZE ; Buffer size
;
; Define a key definition XAB for the primary key.
;
DST_KEY0: ; Primary key is Name
$XABKEY REF=0,- ; Key reference number
DAN=0,- ; Define data XABALL
DFL=1536,- ; Define data fill of 75%
FLG=<DUP>,- ; Allow duplicate keys
DTP=DSTG,- ; Descending sort order
IAN=1,- ; Define index XABALL
IFL=1536,- ; Initial index fill 75%
PROLOG=3,- ; Request prolog 3
POS=<12,0,11>,- ; Key segment positions
SIZ=<15,1,1>,- ; Key segment lengths
NXT=DST_KEY1 ; Address of next XAB in chain
;
; Define key definition XABs for the alternate keys.
;
DST_KEY1: ; 1st alternate key is City
$XABKEY REF=1,- ; Key reference number
DAN=2,- ; Data level (SIDR) XABALL
IAN=2,- ; Index XABALL
IFL=768,- ; Initial index fill 75%
POS=47,- ; Starting key position
SIZ=12,- ; Key size
FLG=<CHG,DUP>,- ; Duplicates and changes
NXT=DST_KEY2 ; Address of next XAB in chain
DST_KEY2: ; 2nd alternate key is State
$XABKEY REF=2,- ; Key reference number
DAN=2,- ; Data level (SIDR) XABALL
IAN=2,- ; Index XABALL
IFL=768,- ; Initial index fill 75%
POS=59,- ; Starting key position
FLG=<CHG,DUP>,- ; Duplicates and changes
SIZ=2,- ; Key size
NXT=DST_ALL0 ; Designate next XAB
;
; Define allocation control XABs to define multiple areas
;
DST_ALL0:
$XABALL AID=0,- ; Data area definition
ALQ=328,- ; Allocation quantity and
AOP=<CBT>,- ; contiguous best try
BKZ=4,- ; Bucket size of 4 blocks
DEQ=112,- ; Default extension quantity
NXT=DST_ALL1 ; Designate next XAB
DST_ALL1:
$XABALL AID=1,- ; Primary key index area
ALQ=8,- ; Allocation quantity and
AOP=<CBT>,- ; contiguous best try
BKZ=4,- ; Bucket size of 4 blocks
DEQ=4,- ; Default extension quantity
NXT=DST_ALL2 ; Designate next XAB
DST_ALL2:
$XABALL AID=2,- ; Alternate key data area
ALQ=112,- ; Allocation quantity and
AOP=<CBT>,- ; contiguous best try
BKZ=2,- ; Bucket size of 2 blocks
DEQ=38,- ; Default extension quantity
NXT=0 ; No more XABs
;
; Allocate buffer to the size of the largest record being read.
;
BUFFER: .BLKB 66 ; Buffer for input and output
BUFFER_SIZE=.-BUFFER ; Buffer size
;*********************************************************************
.SBTTL Mainline
.PSECT CODE NOWRT,BYTE
;
; Start of program
;
.ENTRY CREATEIDX,^M<R6> ; Entry point
;
; Open the source and destination files.
;
$OPEN FAB=SRC_FAB ; Open input file
BLBC R0,EXIT1 ; Branch on failure
$CONNECT RAB=SRC_RAB ; Connect input record stream
BLBC R0,EXIT2 ; Branch on failure
$CREATE FAB=DST_FAB ; Create output file
BLBC R0,EXIT3 ; Branch on failure
$CONNECT RAB=DST_RAB ; Connect output record stream
BLBC R0,EXIT4 ; Branch on failure
BRB LOOP ; Bypass signaling code
EXIT1: MOVAL SRC_FAB,R6 ; Keep FAB address
BRB F_ERR ; Signal error
EXIT2: MOVAL SRC_RAB,R6 ; Keep RAB address
BRB R_ERR ; Signal error
EXIT3: MOVAL DST_FAB,R6 ; Keep FAB address
BRB F_ERR ; Signal error
EXIT4: MOVAL DST_RAB,R6 ; Keep RAB address
BRB R_ERR ; Signal error
;
; Transfer records until end-of-file is reached.
;
LOOP: $GET RAB=SRC_RAB ; Read next rec from input file
BLBS R0,PUT ; Branch on success
CMPL R0,#RMS$_EOF ; Was it end-of-file (EOF)?
BNEQ EXIT2 ; Branch if not EOF error
BRB CLOSE ; Close and exit if EOF
PUT: $PUT RAB=DST_RAB ; Write 66-byte record to output
BLBS R0,LOOP ; On success, continue loop
BRB EXIT4 ; On error, signal and exit
;
; Close the source and destination files.
;
F_ERR: PUSHL FAB$L_STV(R6) ; Push STV and STS fields
PUSHL FAB$L_STS(R6) ; on stack
CALLS #2, G^LIB$SIGNAL ; Signal file error
BRB EXIT ; Exit
R_ERR: PUSHL RAB$L_STV(R6) ; Push STV and STS fields
PUSHL RAB$L_STS(R6) ; on stack
CALLS #2, G^LIB$SIGNAL ; Signal file error
CLOSE: $CLOSE FAB=DST_FAB ; Close output file
$CLOSE FAB=SRC_FAB ; Close input file
EXIT: $EXIT_S ; Exit
.END CREATEIDX ; Specify starting address
|
This example program creates an indexed file with a primary key and two
alternate keys that are defined by appropriate key definition control
blocks (XABKEY).
For efficiency, the file is divided into areas consisting of a data
area and an index area for each key using multiple allocation control
blocks (XABALL).
In each XABKEY, the DAN and IAN arguments (XAB$B_DAN and XAB$B_IAN
fields) indicate the area identification number (AID) of the
corresponding XABALL.
By setting the RAB$V_LOA bit in RAB field RAB$L_ROP, the program
directs RMS to use the DFL and IFL arguments (XAB$W_DFL and XAB$W_IFL
fields) to determine the maximum initial fill size (in bytes) for data
and index buckets (each bucket contains the number of blocks specified
in the XABALL BKZ argument, XAB$B_BKZ field).
These are the XABKEY and XABALL control blocks for the primary key (the
NAME key) in this example:
DST_KEY0: ; Primary key is Name
$XABKEY REF=0,- ; Key reference number
DAN=0,- ; Define data XABALL
DFL=1536,- ; Define data fill of 75%
FLG=<DUP>,- ; Allow duplicate keys
DTP=DSTG,- ; Descending sort order
IAN=1,- ; Define index XABALL
IFL=1536,- ; Initial index fill 75%
PROLOG=3,- ; Request prolog 3
.
.
.
DST_ALL0:
$XABALL AID=0,- ; Data area definition
ALQ=328,- ; Allocation quantity and
AOP=<CBT>,- ; contiguous best try
BKZ=4,- ; Bucket size of 4 blocks
DEQ=112,- ; Default extension quantity
NXT=DST_ALL1 ; Designate next XAB
DST_ALL1:
$XABALL AID=1,- ; Primary key index area
ALQ=8,- ; Allocation quantity and
AOP=<CBT>,- ; contiguous best try
BKZ=4,- ; Bucket size of 4 blocks
DEQ=4,- ; Default extension quantity
NXT=DST_ALL2 ; Designate next XAB
|
The allocation information was obtained using the File Definition
Language (FDL) editor which is especially useful when you are creating
large indexed files.
The DCL commands CREATE/FDL and CONVERT can be used to create files by
using an FDL file produced by the Edit/FDL utility, without any
programming. Instead of using the multiple XABs for the key definition
and area allocations in this program, a simpler approach is to use the
FDL file
produced by the Edit/FDL utility by invoking the FDL routines FDL$PARSE
and FDL$RELEASE (for more information on these routines, see the
OpenVMS Utility Routines Manual).
Fixed-length records are copied from the sequential input file on the
local node to the indexed file on the remote node. Each variable-length
output record is initially 66 bytes long and may be extended to a
maximum of 128 bytes.
|