Trailing-Edge
-
PDP-10 Archives
-
tops20-v7-ft-dist1-clock
-
7-sources/rmserr.b36
There are 28 other files named rmserr.b36 in the archive. Click here to see a list.
%TITLE 'E R R O R S -- Error processor'
!<BLF/REQUIRE 'RMSBLF.REQ'>
MODULE errors (IDENT = '3.0'
) =
BEGIN
!
! COPYRIGHT (C) DIGITAL EQUIPMENT CORPORATION 1986.
! ALL RIGHTS RESERVED.
!
! THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND
! COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH
! THE INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR
! ANY OTHER COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE
! AVAILABLE TO ANY OTHER PERSON. NO TITLE TO AND OWNERSHIP OF THE
! SOFTWARE IS HEREBY TRANSFERRED.
!
! THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT
! NOTICE AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL
! EQUIPMENT CORPORATION.
!
! DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF
! ITS SOFTWARE ON EQUIPMENT THAT IS NOT SUPPLIED BY DIGITAL.
!
!++
! FACILITY: RMS
!
! ABSTRACT:
!
! ERRORS contains all routines which
! process user or system errors.
!
! ENVIRONMENT: User mode, low level
!
! AUTHOR: Ron Lusk , CREATION DATE: 29-Mar-83
!
! MODIFIED BY:
!
! Ron Lusk, 1-Jun-83 : VERSION 2
! 01 - Make PRICHK only allow messages to be printed
! when the debugging version of RMS is compiled.
! 410 - REMOVRECORD has been calling DELUDR with 3
! arguments for years; DELUDR only takes 2 arguments,
! however, and this shows up in XRMS.EXE. Fix
! REMOVRECORD.
! Andy Nourse, 6-Jun-83
! 411 - Implement new key datatypes
! 502 - Put in new-style names
! 504 - Allow 8 or 9 bit ASCII, and (1<n<36)-bit IMAGE
! 607 - Use FAB bsz instead of FST when checking DTP KEY XABs. NOTE:
! CHECKXAB is now called before the FST is fully updated from
! the user's FAB.
!--
!
! TABLE OF CONTENTS
!
!
! DOEOF - Process EOF condition
! CRASH - Process internal RMS-20 error
! PRICHK - Check if message should be output
! FERROR - Check for $OPEN/$CREATE user errors
! OABORT - Abort $OPEN/$CREATE processing and
! unwind all that has been done up to
! the point where error was detected.
! CHECKXAB - Scan XAB chain for errors during $CREATE
! CLEANUP - Clean up after $PUT error for indexed file
! REMOVRECORD - Similar to CLEANUP, but record must be
! removed from secondary indices.
! MAPCODES - Map system errors to RMS error codes
!
!
! INCLUDE FILES:
!
REQUIRE 'rmsreq';
!
! MACROS:
!
! None.
!
! EQUATED SYMBOLS:
!
! See RMSSYS, RMSLIB
!
! OWN STORAGE:
!
! See RMSGLB
!
! EXTERNAL REFERENCES:
!
! Also See RMSEXT
!
EXTERNAL ROUTINE Dap$EndAccess;
%SBTTL 'DOEOF - Handle EOF'
GLOBAL ROUTINE doeof : NOVALUE =
!++
! FUNCTIONAL DESCRIPTION:
!
! This routine is called whenever the End-of-File is
! reached on a sequential or a relative file. Its
! function is to unlock the current record and perform any
! other clean-up operations which may be necessary.
!
! FORMAL PARAMETERS
!
! None.
!
! IMPLICIT INPUTS
!
! ?
!
! ROUTINE VALUE:
!
! None.
!
! SIDE EFFECTS:
!
! ?
!
!--
BEGIN
LOCAL
crp;
!+
! Unlock the current record.
!-
crp = .rst [rstdatarfa]; ! Get its address
IF datalocked THEN unlock (crp); ! Unlock it, if necessary
rab [rabrsz, 0] = 0; ! Tell him he has a null record
rst [rstdatarfa] = 0; ! Clear our knowledge
usererror (er$eof) ! Give user error
END; ! End of DOEOF
%SBTTL 'CRASH - print internal error message'
GLOBAL ROUTINE crash (rname, txtadr) : exitsub NOVALUE =
!++
! FUNCTIONAL DESCRIPTION:
!
! This routine is called whenever an internal
! consistency error is detected. Its purpose is to
! print out a diagnostic message and to halt
! processing. No attempt is made to recover from the
! problem.
!
! Note:
! This routine fetches the return PC by "indexing"
! off the last argument passed to the routine.
!
! FORMAL PARAMETERS
!
!
! RNAME - presumably the routine name [RL, Mar-83]
!
! TXTADR - address of an n+1 word block:
! first word contains error code;
! second through n+1 contain message text.
!
! IMPLICIT INPUTS
!
! ?
!
! ROUTINE VALUE:
!
! None.
!
! SIDE EFFECTS:
!
! ?
!
!--
BEGIN
LOCAL
returnadr; ! Contains the return PC
!++
! NOTE:
! This routine displays the PC. If more arguments
! are added to it, the value of RETURNADR must be
! recomputed; the existing formula will not work.
!--
IF (.bugcod NEQ .txtadr) AND ! Is this a new message?
(chkflag (rmssts, stsnomessage) EQL 0) ! Should we print messages?
THEN
BEGIN ! Yes -- go ahead
returnadr = .(txtadr + 1); ! Fetch return PC
txtout ( ! Print message
mf$ier, ! Internal error format
.rname, ! Routine name
.returnadr<rh> - 1, ! Address we were called from
.txtadr + 1); ! Address of message text
END;
bugcod = .txtadr; ! Save this address
usrsts = ..txtadr; ! Setup error code for user
usrstv = .txtadr + 1; ! Pointer to text message
usrerr () ! Exit to user
END; ! End of CRASH
%SBTTL 'PRICHK - should message be output'
GLOBAL ROUTINE prichk (txtadr) =
!++
! FUNCTIONAL DESCRIPTION:
!
! PRICHK checks if message should be output to terminal.
! As of v2, PRICHK will never allow messages to be typed
! unless RMS is compiled with debugging code.
!
! FORMAL PARAMETERS
!
! TXTADR - value of USRSTV, which should
! be the address of a message.
!
! IMPLICIT INPUTS
!
! None.
!
! COMPLETION CODES:
!
! TRUE - output message
! FALSE - do not output message
!
! SIDE EFFECTS:
!
! ?
!
!--
BEGIN
%IF NOT DBUG
%THEN
RETURN false;
%ELSE
IF .usrsts NEQ er$bug THEN RETURN false; ! Message N/A unless ER$BUG
!+
! Check to see if the current bug is the same as the last one.
! If so, we will just exit and not do any useful work. If not,
! we will print out the message for this bug and return to the user.
!-
IF (.bugcod EQL .txtadr) THEN RETURN false;
bugcod = .txtadr; ! Save the new value
IF (chkflag (rmssts, stsnomessage) EQL 0) !
THEN
RETURN true
ELSE
RETURN false;
%FI ! End debugging code
END; ! End of PRICHK
%SBTTL 'FERROR - check for errors opening file'
GLOBAL ROUTINE ferror =
!++
! FUNCTIONAL DESCRIPTION:
!
! FERROR analyzes the user's requests to $OPEN a file
! and checks it for errors. When FERROR entered, the
! FAB and FPT must have been initialized. On exit,
! the appropriate error code will have been set in
! USRSTS. In general, this routine will always exit
! to the caller if an error is discovered.
!
! FORMAL PARAMETERS
!
! None.
!
! IMPLICIT INPUTS
!
! ?
!
! COMPLETION CODES:
!
! TRUE - No errors found.
!
! FALSE - Error
! ASCII files:
! 1. FB$BLK is illegal
! 2. Update and deletes are not allowed
! 3. Only one writer of the file is allowed
! 4. Byte size must be 7, 8, or 9
!
! IMAGE files:
! 1. FB$BLK is illegal
! 2. Update and deletes are not allowed
! 3. Only one writer of the file is allowed
! RMS files:
! 1. Must be DASD (disk) if relative file
! 2. MRS must be nonzero for relative file
! 3. Device must be DASD (restriction on v1)
!
! All files:
! 1. Unused attributes must be zero
! 2. Various values must be within proper range
! 3. Record format must agree with file organization.
!
!
! SIDE EFFECTS:
!
! ?
!
!--
BEGIN
LOCAL
temp;
TRACE ('FERROR');
!+
! Make sure that the record format agrees with the organization.
!-
IF ((stream) OR (sequenced)) AND !
( NOT asciifile) !
THEN
returnstatus (er$rfm); ! ASCII/LSA must be sequential
!+
! Check ASCII file errors.
!-
IF asciifile ! Non-RMS file
THEN
BEGIN
SELECT .Fst [Fst$h_Rfm] OF ! RFM determines restriction !a504
SET
[Fab$k_Lsa]:
IF .fab [Fab$v_Bsz] NEQ asciibytesize ! Check byte size
THEN
returnstatus (er$bsz);
[Fab$k_Stm]:
IF (.Fab [Fab$v_Bsz] LSS 7)
OR (.Fab [Fab$v_Bsz] GTR 9)
THEN
returnstatus (er$bsz);
[Fab$k_Udf]:
IF (.Fab [Fab$v_Bsz] EQL 0) ! There must be some
OR (.Fab [Fab$v_Bsz] GTR %BPUNIT) ! limits.
THEN
returnstatus (er$bsz);
TES;
IF blocked !
THEN
returnstatus (er$rat); ! Records must span pages
!+
! Don't allow multiple writers to disk.
!-
IF (((.fab [fabfac, 0] AND ! Is he...
.fab [fabshr, 0] AND ! ...and are others...
axput) NEQ 0) AND ! ...writing the file...
dasd) ! ...to a disk device?
THEN
returnstatus (er$fac);
!+
! If this is a sequenced file on the TTY:, it cannot
! be opened for both input and output.
!-
IF sequenced AND tty AND iomode !
THEN
returnstatus (er$fac)
END;
!+
! RMS file errors
!-
IF rmsfile
THEN
BEGIN
!+
! Check that the MRS field is being used correctly.
!-
IF .fab [fabmrs, 0] EQL 0
THEN
BEGIN
IF relfile OR fixedlength ! MRS needed for relative, fix
THEN
returnstatus (er$mrs)
END;
IF NOT dasd ! Must be disk
THEN
returnstatus (er$dev);
END;
!+
! Check various parameters.
!-
IF fileorg GTR orgmax ! Check organization value
THEN
returnstatus (er$org);
IF (.fab [fabbsz, 0] GTR 36) OR ! Reasonable bytesize
(.fab [fabbsz, 0] EQL 0) ! Cannot be zero
THEN
returnstatus (er$bsz); ! Check byte size
!+
! For compatibility, make sure that the unused
! RAT bits are not set.
!-
IF (.fab [fabrat, 0] AND ratunused) NEQ 0 ! Check undefined RAT bits
THEN
returnstatus (er$rat);
IF .fab [fab$v_rfm] GTR Fab$k_Rfm_Max ! Check record format !m504
THEN
returnstatus (er$rfm);
IF fileaccess EQL 0 ! Don't allow null FAC
THEN
returnstatus (er$fac);
RETURN true
END; ! End of FERROR
%SBTTL 'OABORT - unwind $OPEN/$CREATE operation'
GLOBAL ROUTINE oabort (errorcode) : exitsub NOVALUE =
!++
! FUNCTIONAL DESCRIPTION:
!
! OABORT processes the aborting of $OPEN or $CREATE.
! It is called whenever an error is found in the $OPEN
! processing. This routine performs any necessary
! clean-up and exits directly to the user. This
! technique is used to simplify the flow of the $OPEN
! processor.
!
! FORMAL PARAMETERS
!
! ERRORCODE - value to return in USRSTS or, if 0,
! code that OABORT was called from
! USRRET code.
!
! IMPLICIT INPUTS
!
! OAFLAGS - Flags for unwinding
! ABRUNLOCK - Unlock file
! ABRCLOSE - Close file
! ABRFST - Release File Status Table
! ABRPLOGPAGE - Release free page used for prologue
! ABRADB - Release the Area Descriptor Block
!
! ROUTINE VALUE:
!
! None.
!
! SIDE EFFECTS:
!
! ?
!
!--
BEGIN
LOCAL
flags,
temp : REF BLOCK;
TRACE ('OABORT');
flags = .oaflags; ! Use local to avoid
oaflags = 0; ! possible recursive
! error loop.
!+
! Unlock file resources if locked.
!-
IF (.flags AND abrunlock) NEQ 0 THEN fileq (deqcall, deqdr);
!+
! Release core for File Prologue Table.
! Note that this page must be unmapped before the file is closed.
!-
IF ((.flags AND abrplogpage) NEQ 0) !
THEN
ppage (.plogpage, 1, true);
!+
! Close file.
!-
IF (.flags AND abrclose) NEQ 0
THEN
BEGIN
abortfile (.userjfn, .fab); ! User JFN and address of FAB
END;
!+
! Release core for File-Status Table.
!-
IF ((.flags AND abrfst) NEQ 0)
THEN
BEGIN
!+
! First, we must release all key descriptors for this
! file. For non-indexed files, there won't be any key
! descriptors. For indexed files, the only situation in
! which there would be a KDB chain that we will have to
! flush is if the user gave an XAB chain on the $OPEN and
! there was an error during its processing, or if the file
! is remote (so we need the key datatypes even if the user doesn't)
!-
undokdbs (); ! Flush all KDBs
temp = .fst [blocklength];
IF .Fst[Fst$v_Remote] ! If the file is remote !a521vv
THEN ! Make sure we close the link
BEGIN
Dap$EndAccess( .fab, Dap$k_Accomp_Purge, 0);
IF .Fst[Fst$v_Drj] EQL 0 ! If link not held open
THEN
BEGIN
Fab[Fab$a_Ifi] = 0; ! Clear IFI for sure !a577
pmem (.temp, fst) ! Return memory
END;
END !a521^^
ELSE
BEGIN
Fab[Fab$a_Ifi] = 0; ! Clear IFI for sure !a577
pmem (.temp, fst)
END;
END;
!+
! Release core for Area Descriptor Block.
!-
IF ((.flags AND abradb) NEQ 0)
THEN
BEGIN
temp = .adb [adb$h_bln]; ! Get length of FST !m502
pmem (.temp, adb) ! Release core
END;
IF .errorcode EQL 0 THEN RETURN; ! Called from USRRET
usrsts = .errorcode; ! Store error code
usrerr ()
END; ! End of OABORT
%SBTTL 'CHECKXAB -- Find XAB errors'
GLOBAL ROUTINE checkxab =
!++
! FUNCTIONAL DESCRIPTION:
!
! This routine scans the XAbs of the user on a
! $CREATE. It checks the following things:
! 1) Block-type
! 2) XAB code-type (Key, Allocation, etc.)
! 3) Data-type
! 4) Flags
! 5) Key of reference value
! 6) Key position and size
! 7) Index and data fill offsets
! 8) Order of the XABs
!
! FORMAL PARAMETERS
!
! None.
!
! IMPLICIT INPUTS
!
! ?
!
! COMPLETION CODES:
!
! TRUE - Success
! FALSE - Error code in USRSTS
!
! SIDE EFFECTS:
!
! ?
!
!--
BEGIN
REGISTER
xabptr : REF BLOCK; ! Pointer to the user XAB
LOCAL
temp,
krfcount, ! Counter used to insure
! KRFs are in order
totalsize, ! Accumulator
keybytesize, ! Byte size of the key string
aidcount, ! Count for sequencing AIDs
ksdptr : REF BLOCK; ! Key Segment Descriptor
TRACE ('CHECKXAB');
!
! Get the start of the XAB chain
!
xabptr = .fab [fabxab, 0]; ! Fetch pointer from FAB
!
! Initialize counter of current value of the key reference
!
krfcount = 0;
aidcount = 1; ! Use default area to start
!+
! We must first find the area XABs and check them.
! Then, we will scan for the key XABs later.
!-
WHILE .xabptr NEQ 0 DO
BEGIN
usrstv = .xabptr; ! Save address of bad XAB
xabptr = .xabptr OR .blksec; ! Get global address
IF .xabptr [blocktype] NEQ xabcode ! Is this a XAB?
THEN
returnstatus (er$xab); ! No
IF .xabptr [xabcod, 0] GTR maxcod ! Valid COD field?
THEN
returnstatus (er$cod); ! No
temp = .xabptr [xabnxt, 0]; ! Get next XAB address
IF (.temp NEQ 0) AND ! XAB in regs?
(.temp LEQ minuserbuff)
THEN
returnstatus (er$nxt); ! Bad next address
IF .xabptr [xabcod, 0] EQL codarea
THEN
BEGIN
!
! Check the size of this XAB.
!
IF .xabptr [blocklength] NEQ areaxabsize !
THEN
returnstatus (er$bln);
IF .xabptr [xabaid, 0] NEQ .aidcount !
THEN
returnstatus (er$aid);
IF (.xabptr [xabbkz, 0] GTR maxbkz) OR !
(.xabptr [xabbkz, 0] EQL 0) !
THEN
returnstatus (er$bkz); ! Check bucket size
aidcount = .aidcount + 1
END;
xabptr = .xabptr [xabnxt, 0] ! Go to next XAB
END;
!+
! Now, we will start all over again and search for KEY XABs.
!-
xabptr = .fab [fabxab, 0]; ! Get XAB chain pointer
WHILE .xabptr NEQ 0 DO
BEGIN
usrstv = .xabptr; ! Save address of bad XAB
xabptr = .xabptr + .blksec; ! Get global address
IF .xabptr [xabcod, 0] EQL codkey !
THEN
BEGIN
!+
! Check the size of the XAB.
!-
IF .xabptr [blocklength] NEQ keyxabsize !
THEN
returnstatus (er$bln);
!+
! Check the data type of this key.
!-
IF .xabptr [xabdtp, 0] GTR maxdtp !
THEN
returnstatus (er$dtp);
!+
! Check that the key of reference values are in order.
!-
IF .xabptr [xabref, 0] NEQ .krfcount !
THEN
returnstatus (er$ref);
!+
! Find the byte size for this key.
!-
keybytesize = .dtptable [.xabptr [xabdtp, 0], dtpbytesize];
IF (.keybytesize NEQ .Fab [Fabbsz, 0]) !Bsize must match !M607
AND (.keybytesize LSS %BPVAL) ! unless binary data !A411
THEN
returnstatus (er$dtp);
!+
! Check that the flags don't contradict.
!-
IF ((.xabptr [xabflg, 0] AND flgchange) NEQ 0)
THEN
BEGIN ! Keys can change, check more
IF .krfcount EQL refprimary ! Must not be primary key
THEN
returnstatus (er$flg)
END;
!+
! Check the index and data area numbers.
!-
IF .xabptr [xabian, 0] GEQ .aidcount ! Must be known area
THEN
returnstatus (er$ian);
IF .xabptr [xabdan, 0] GEQ .aidcount ! Must also exist
THEN
returnstatus (er$dan);
!+
! Set up pointer to key segment descriptors.
!-
ksdptr = .xabptr + xabksdoffset;
totalsize = 0;
INCR i FROM 0 TO maxkeysegs - 1 DO
totalsize = .totalsize + .ksdptr [.i, keysiz];
!+
! Check the length of the key.
!-
IF (.keybytesize LSS %BPVAL) ! If byte-oriented data !A411
AND ((.totalsize GTR maxkeysize) OR ! Range Check !M411
(.totalsize EQL 0)) ! total key size !M411
THEN
returnstatus (er$siz);
krfcount = .krfcount + 1 ! Bump KRF total
END;
!+
! Check that this was a valid type of XAB.
!-
IF .xabptr [xabcod, 0] GTR maxcod !
THEN
returnstatus (er$cod);
IF .xabptr [blocktype] NEQ xabcode !
THEN
returnstatus (er$xab);
!+
! Fetch the address of the next XAB in the chain.
!-
xabptr = .xabptr [xabnxt, 0] ! Next block
END;
!+
! Now, check that there are not too many key or area XABs
!-
usrstv = 0; ! These errors not XAB specific
IF .krfcount GTR maxkeys + 1 THEN returnstatus (er$imx);
IF .aidcount GTR maxareas THEN returnstatus (er$imx);
IF .krfcount EQL 0 THEN returnstatus (er$npk); ! No primary key
! No error found.
RETURN true;
END; ! End of CHECKXAB
%SBTTL 'CLEANUP - Clean up after failed $PUT'
GLOBAL ROUTINE cleanup (bktdesc : REF BLOCK) : NOVALUE =
!++
! FUNCTIONAL DESCRIPTION:
!
! CLEANUP cleans up some operations after a $PUT has
! failed. This routine must perform the folloing
! functions:
! 1) Unlock the index structure
! 2) Release the current bucket
!
! The index structure is unlocked if the appropriate
! bit is set in the FST flags field. The bucket
! descriptor is released if it is non-null.
!
! USRSTS must be set up by the caller to reflect the
! correct error code.
!
! This routine will return or not depending on the
! value of OAFLAGS.
!
! FORMAL PARAMETERS
!
! BKTDESC - bucket to release
!
! IMPLICIT INPUTS
!
! ?
!
! ROUTINE VALUE:
!
! None.
!
! SIDE EFFECTS:
!
! ?
!
!--
BEGIN
LOCAL
indexnumber; ! Number of current index
TRACE ('CLEANUP');
!+
! Check if we should unlock the index.
!-
IF indexlocked THEN unlockindex;
!+
! Should we release the current bucket.
!-
IF NOT nullbd (bktdesc) !
THEN
putbkt (false, ! No update
.bktdesc); ! Bucket pointer
!+
! Should we return to the caller or to the user?
!-
IF .oaflags NEQ 0 !
THEN
RETURN !
ELSE
usrerr (); !
END; ! End of CLEANUP
%SBTTL 'REMOVRECORD - Clean up secondary indexes'
GLOBAL ROUTINE removrecord ( ! Clean up indexes
recdesc : REF BLOCK, ! User record
databd : REF BLOCK ! Record's bucket
) : NOVALUE =
!++
! FUNCTIONAL DESCRIPTION:
!
! Routine to clean up after a $PUT for an indexed file
! has failed in some way during processing of the
! secondary indexes. This routine differs from
! CLEANUP in that it is more specialized--it must
! delete the date record from some of the secondary
! indexes.
!
! Specifically, this routine does the following:
!
! 1) Delete the record from all previous
! secondary indexes.
! 2) Compress the data record from the data
! bucket.
! 3) Unlock the index structure of the file.
!
! If any problem develops during the deletion of a
! SIDR record pointer, then the primary data record
! will be marked with the DELETED and NO-COMPRESS
! bits. This means that the UDR will stay around
! forever if any of its secondary index entries cannot
! be deleted properly.
!
! KDB must point to the secondary index KDB which failed.
!
! The error code must already be set up in USRSTS.
!
! <><><><> This routine exits directly to the user. <><><><><>
!
! FORMAL PARAMETERS
!
! RECDESC - Record descriptor packet
! RFA - RFA of record to compress out
!
! DATABD - Descriptor of data bucket
!
! IMPLICIT INPUTS
!
! ?
!
! ROUTINE VALUE:
!
! None.
!
! SIDE EFFECTS:
!
! ?
!
!--
BEGIN
LABEL
flushsidr;
LABEL
sidrloop; ! Loop for all SIDR records
LOCAL
failkdbaddress, ! Address of bad KDB
ourbuffer : BLOCK [maxkszw], ! Use as temp buffer
userrecordptr : REF BLOCK, ! User data record
savedstatus, ! Saved status code
savederrorcode, ! Error code on entry
fixsidrflag, ! True if all SIDRs deleted
savedrfa, ! Remember the RFA of UDR
sizeofthisrcrd, ! For compressing
amounttomove;
REGISTER
tempac,
bktptr : REF BLOCK, ! Data bucket
udrptr : REF BLOCK; ! User data record
TRACE ('REMOVRECORD');
savederrorcode = .usrsts; ! Save the proper code
!+
! Save the bad KDB address and set up some miscellaneous things.
!-
failkdbaddress = .kdb;
userrecordptr = .rab [rabrbf, 0];
!+
! Incase he specified a local section address in "RBF"...
!-
IF .userrecordptr<lh> EQL 0 !
THEN
userrecordptr = .userrecordptr OR .blksec;
recdesc [rduserptr] = ourbuffer; ! ADDR OF KEY
!+
! Loop over all KDBs and delete the record in that index.
!-
kdb = .fst [fstkdb]; ! Primary index
kdb = .kdb [kdbnxt]; ! First secondary index
IF .kdb [blocktype] NEQ kdbcode THEN rmsbug (msgkdb);
fixsidrflag = true; ! Assume we succeed
!++
! This is the loop through the indexes.
!--
sidrloop :
BEGIN
UNTIL .kdb EQL .failkdbaddress DO
BEGIN
!+
! Only delete the record if it was inserted.
!-
IF .rab [rabrsz, 0] GEQ .kdb [kdbminrsz] !
! %(AND)%
! %(THIS IS NOT THE NULL KEY VALUE)%
THEN
flushsidr :
BEGIN
!+
! Move the secondary key into a temporary buffer.
!-
movekey (.userrecordptr, ! From
ourbuffer); ! To
!+
! Set up the key size.
!-
recdesc [rdusersize] = .kdb [kdbksz];
!+
! Delete record from secondary index. If it fails, stop deleting.
!-
IF delsidr (.recdesc) EQL false !
THEN
LEAVE sidrloop WITH (fixsidrflag = false)
END;
!+
! Advance to next KDB.
!-
kdb = .kdb [kdbnxt]
END;
END;
!+
! Now, go back and locate the user data record.
!-
kdb = .fst [fstkdb]; ! Set primary key
recdesc [rdrecptr] = 0; ! Start at top
recdesc [rdrfa] = .recdesc [rdrrv]; ! Search for new UDR
!+
! Locate the user data record with POSRFA, which will
! Search for the newly inserted record by RFA, which was
! Just placed in RECDESC [ RDRFA ]. SDATABKT was
! Originally used here, but when the new record went into a
! Separate bucket on a bucket split, SDATABKT would do an
! ID search of the current bucket and the wrong UDR would
! Be deleted by REMOVRECORD.
!-
IF posrfa (.recdesc, ! Record
.databd) EQL false ! Bucket
THEN
rmsbug (msgfailure);
!+
! If we didn't find it, there is a problem, because the
! bucket was never unlocked.
!-
!+
! ***TAKE BEFORE IMAGE HERE***
!-
!+
! Get the address of the data record.
!-
udrptr = .recdesc [rdrecptr];
recdesc [rdlength] = sizeofudr (udrptr);
!+
! If we successfully deleted all secondary data records,
! then we can squeeze out the primary data record. If
! not, we can only delete if but must leave it intact so
! that an existing secondary index doesn't point to a
! non-existent data record.
!-
IF .fixsidrflag NEQ false
THEN
deludr (.recdesc, ! Record descriptor
.databd) ! Bucket descriptor !M410
! true) ! Lock it !D410
ELSE ! Mark the record as deleted
setflag (udrptr [drflags], flgdelete + flgnocompress);
!+
! Now release the data bucket and update it to the disk
! (because we have already written it to the disk when we
! thought the operation would be a success.
!-
putbkt (true, ! Do update
.databd); ! Bucket to release
!+
! Unlock the file index structure, if it was locked.
!-
IF indexlocked THEN unlockindex;
!+
! Exit to user.
!-
usrsts = .savederrorcode; ! Restore correct error code
usrerr ();
END; ! End of REMOVRECORD
%SBTTL 'MAPCODES - system errors to RMS errors'
GLOBAL ROUTINE mapcodes ( ! Sys errors to RMS errors
systemcode, ! TOPS-20 code
defaultcode, ! Default RMS code
maptable : REF BLOCK ! Address of mapping table
) : exitsub NOVALUE =
!++
! FUNCTIONAL DESCRIPTION:
!
! MAPCODES performs all mapping of TOPS-20 error codes
! (returned from monitor calls) to the appropriate
! RMS-20 error codes. This routine simply takes the
! TOPS-20 code which was returned and searches an
! error-mapping table supplied by the caller to
! determine if the system error code is in the table.
! If so, the corresponding RMS-20 error code is
! substituted for the system error code. If not, the
! default RMS-20 error code is stored in the user's
! STS field (USRSTS) and the system error code is
! stored in the STV field.
!
! The format of the Error Mapping Table (EMT) is
!
!
! |-------------------------------------|
! | <Assoc RMS code> | System Code 1 |
! |-------------------------------------|
! | <Assoc RMS code> | System Code 2 |
! |-------------------------------------|
! | . |
! |-------------------------------------|
! | . |
! |-------------------------------------|
! | . |
! |-------------------------------------|
! | <Assoc RMS code> | System Code n |
! |-------------------------------------|
! | 0 |
! |-------------------------------------|
!
!
! The setting of OAFLAGS determines whether this
! routine returns to the caller or exits directly
! to the user.
!
! FORMAL PARAMETERS
!
! SYSTEMCODE - Code returned by TOPS-20
! DEFAULTCODE - RMS-20 error code to be used if
! SYSTEMCODE is not found in Error
! Mapping Table
! MAPTABLE - Address of Error Mapping Table
!
! IMPLICIT INPUTS
!
! ?
!
! IMPLICIT OUTPUTS
!
! xxxSTS - Modified to contain RMS code (xxx is FAB or RAB)
! xxxSTV - Modified to contain System code
! USRSTS - Modified to contain RMS code
!
! ROUTINE VALUE:
!
! NONE.
!
! SIDE EFFECTS:
!
! ?
!
!--
BEGIN
REGISTER
mapindex, ! Used to index into table
tableptr : REF BLOCK; ! Pointer to mapping table
TRACE ('MAPCODES');
!+
! Set up the default RMS-20 error code in user status field.
!-
usrsts = .defaultcode;
usrstv = .systemcode; ! Save system code
!+
! Initialize index variable.
!-
mapindex = 0;
tableptr = .maptable; ! Get address of table
!+
! Do this loop for each entry in the mapping table. When
! the end of the table is reached, we can exit because we
! have already set up the default error code.
!-
UNTIL .tableptr [.mapindex, wrd] EQL 0 DO
BEGIN
!+
! Check if this error code is in the table and then add a
! lot of garbage to the comment.
!-
IF .tableptr [.mapindex, emtsyscode] EQL .systemcode
THEN ! We found the error code
BEGIN
usrsts = .tableptr [.mapindex, emtrmscode];
EXITLOOP;
END;
!+
! Bump the table index.
!-
mapindex = .mapindex + sizeofemtentry;
END;
!+
! Return to user or caller.
!-
usrerr ();
END; ! End of MAPCODES
END ! End of Module ERRORS
ELUDOM