Trailing-Edge
-
PDP-10 Archives
-
cuspbinsrc_2of2_bb-fp63b-sb
-
10,7/rms10/rmssrc/rmserr.b36
There are 28 other files named rmserr.b36 in the archive. Click here to see a list.
MODULE ERRORS =
BEGIN
GLOBAL BIND ERROV = 1^24 + 0^18 + 17; !EDIT DATE: 30-DEC-81
%([
FUNCTION: THIS MODULE CONTAINS ALL ROUTINES WHICH PROCESS
USER OR SYSTEM ERRORS.
THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
!COPYRIGHT (C) 1977, 1981 BY DIGITAL EQUIPMENT CORPORATION
AUTHOR: S. BLOUNT/RL
********** TABLE OF CONTENTS **************
ROUTINE FUNCTION
======= ========
DOEOF PROCESS AN EOF CONDITION
CRASH PROCESS AN INTERNAL RMS-20 ERROR
PRICHK CHKS IF MSG SHOULD BE OUTPUT
FERROR CHECK FOR ALL OPEN/CREATE USER ERRORS
OABORT ABORT THE OPEN/CREATE PROCESSING AND
UNWIND ALL THAT HAD BEEN DONE UP TO
THE POINT THAT THE USER ERROR WAS DETECTED
CHECKXAB SCAN XAB CHAIN FOR ERRORS DURING $CREATE
CLEANUP CLEAN-UP AFTER A $PUT FAILURE FOR INDEXED FILE
REMOVRECORD SIMILAR TO CLEANUP EXCEPT THE RECORD MUST
BE DELETED FROM SOME SECONDARY INDICES
MAPCODES PERFORM MAPPING FROM SYSTEM TO RMS ERROR CODES
REVISION HISTORY:
EDIT WHO DATE PURPOSE
==== === ==== ========
1 7-15 UNMAP PLOGPAGE BEFORE CLOSING THE FILE
2 JK 20-JUL-76 TEXT ARG TO 'CRASH' AND 'FPROBLEM' POINTS TO
WORD CONTAINING USER ERROR CODE FOLLOWED BY
WORDS CONTAINING TEXT OF MESSAGE.
3 SB 7-SEP-76 ADD REMOVRECORD
4 SB 8-SEP-76 REMOVE MAX KEYPOS ERROR
5 SB 22-SEP-76 TAKE OUT CHECK FOR DUPS ON PRIMARY KEY
6 SB 22-SEP-76 TAKE OUT CHECK FOR MAXFILLPERCENT
7 SB 18-OCT-76 ADD ERNPK IN CHECKXAB
8 SB 18-OCT-76 ADD CHECK FOR BAD COD VALUE IN CHECKXAB
9 SB 18-OCT-76 ADD LOCKING IN REMOVRECORD
10 SB 1-NOV-76 DELETE FPROBLEM
11 SB 11-NOV-76 ADD CHECK FOR ZERO BKS IN CHECKXAB
12 SB 8-DEC-76 PUT CHECK FOR PRIMARY KEY CHANGE IN CHKXAB
13 SB 23-DEC-76 UNDO EDIT 11
14 SB 13-JAN-77 ADJUST CHECKXAB TO GIVE BETTER ERRORS
15 SB 31-JAN-77 CHANGE CHECKXAB SO AREA XAB'S MAY COME ANYWHERE
*************************************************
* *
* NEW REVISION HISTORY *
* *
*************************************************
PRODUCT MODULE SPR
EDIT EDIT QAR DESCRIPTION
====== ====== ===== ===========
***** Release of Version 1.0 *****
55 16 20-16698 Given an indexed file with two keys (key 0
allows duplicates, key 1 is no duplicates), if
a duplicate record is written to the file such
that a 3-way split occurs, the no-duplicate
second key will cause REMOVRECORD to be called
to back out the data record. However,
REMOVRECORD searches only the current data
bucket for the ID of the new record, not the
new bucket created for that record. When the
record is deleted, it is the wrong record and
the file begins to get corrupted. This is
cured by using POSRFA instead of SDATABKT to do
an RFA search for the duplicate record rather
than an ID search of only one bucket.
****************** Start RMS-10 V1.1 *********************
********************* TOPS-10 ONLY ***********************
PRODUCT MODULE SPR
EDIT EDIT QAR DESCRIPTION
====== ====== ===== ===========
100 17 Dev Make declarations for routine names
be EXTERNAL ROUTINE so RMS will compile
under BLISS V4 (RMT, 10/22/85).
***** END OF REVISION HISTORY *****
])%
EXTERNAL
BUGCOD; ! PLACE TO STORE LAST BUG CODE
EXTERNAL ROUTINE
DELSIDR, ! DELETE A SIDR RECORD
FILEQ,
MOVEKEY, ! MOVE A KEY STRING
SDATABKT, ! SEARCH A DATA BUCKET
PLOGPAGE,
PUTBKT, ! RELEASE A BUCKET
LOCKIT;
%([ ERROR MESSAGES REFERENCED WITHIN THIS MODULE ])%
EXTERNAL
MSGKDB, ! SOMETHING WRONG WITH KDB
MSGFAILURE, ! A ROUTINE FAILED
MSGINPUT; ! BAD INPUT ARGUMENT
FORWARD ROUTINE CRASH: NOVALUE;
REQUIRE 'RMSREQ';
EXTDECLARATIONS;
! DOEOF
! =====
! 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 IN THE FUTURE
! INPUT:
! <NONE>
! OUTPUT:
! <NONE>
GLOBAL ROUTINE DOEOF: NOVALUE =
BEGIN
LOCAL
CRP;
%([ UNLOCK THE CURRENT RECORD ])%
CRP = .RST [ RSTDATARFA ]; ! GET ITS ADDRESS
IF DATALOCKED THEN UNLOCK ( CRP ); ! UNLOCK IT, IF NECESSARY
RAB [ RABRSZ ] = ZERO; ! TELL HIM HE HAS A NULL RECORD
RST [ RSTDATARFA ] = ZERO; ! CLEAR OUR KNOWLEDGE
ERROR ( ER$EOF ) ! GIVE USER ERROR
END; %( OF DOEOF )%
! CRASH
! =====
! THIS ROUTINE IS CALLED WHENEVER AN INTERNAL CONSISTENCY ERROR IS
! FOUND. ITS PURPOSE IS TO PRINT OUT A DISGNOSTIC MESSAGE
! AND TO HALT PROCESSING. NO ATTEMPT IS MADE TO RECOVER
! FROM THE PROBLEM .
! INPUT:
! TXTADR = ADDRESS OF AN N+1 WORD BLOCK:
! FIRST WORD CONTAINS ERROR CODE
! SECOND THROUGH N+1 CONTAIN MESSAGE TEXT
! OUTPUT:
! <NONE>
GLOBAL ROUTINE CRASH ( TXTADR ): NOVALUE =
BEGIN
LOCAL
RETURNADR; ! CONTAINS THE RETURN PC
!NOTE: This routine displays the PC. So if more arguments are added to it
! the value of RETURNADR must be recomputed. The existing technique does
! not work.
ARGUMENT (TXTADR,BASEADD);
%([ IF WE ARE NOT PRINTING MESSAGES...DON'T DO IT ])%
%([ 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 ISNT .TXTADR) AND (CHKFLAG (RMSSTS, STSNOMESSAGE) IS OFF)
THEN BEGIN !INTERNAL ERROR MSG
RETURNADR = .( TXTADR + 1 );
TXTOUT(RM$IER, .ROUTINENAME, .RETURNADR<RH>-1, .TXTADR+1);
END; ! OF IF THIS IS A NEW BUG CODE
BUGCOD = .TXTADR; ! SAVE THIS ADDRESS
USRSTS = ..TXTADR; ! SETUP ERROR CODE FOR USER
USRSTV = .TXTADR + 1; ! RET PTR TO TEXT MSG
USEXITERR ! EXIT TO USER
END; %( OF CRASH )%
! PRICHK
! =====
! THIS ROUTINE CHECKS IF MSG SHOULD BE OUTPUT TO TERMINAL
! INPUT:
! VALUE OF USRSTV
! OUTPUT:
! TRUE IF MESSAGE SHOULD BE OUTPUT, FALSE OTHERWISE
GLOBAL ROUTINE PRICHK ( TXTADR ) =
BEGIN
IF .USRSTS NEQ ER$BUG THEN BADRETURN; ![%50] MSG 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 BADRETURN;
BUGCOD = .TXTADR; ! SAVE THE NEW VAL
IF ( CHKFLAG ( RMSSTS, STSNOMESSAGE ) IS OFF )
THEN GOODRETURN
ELSE BADRETURN;
END; %( OF PRICHK )%
! FERROR
! ======
! THIS ROUTINE ANALYZES THE USER'S REQUESTS TO $OPEN
! A FILE AND CHECKS IT FOR ERRORS.
! WHEN 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
!
! INPUT:
! <NONE>
! OUTPUT:
! TRUE: NO ERRORS FOUND
! FALSE: ERROR
!
! { THE FOLLOWING ERRORS ARE DETECTED BY THIS ROUTINE ]
!
! ASCII FILES:
! 1. FB$BLK IS ILLEGAL
! 2. UPDATE AND DELETES ARE NOT ALLOWED
! 3. ONLY 1 WRITER OF THE FILE IS ALLOWED SIMULTANEOUSLY
! 4. THE BYTE SIZE MUST BE 7.
!
! RMS FILES:
! 1. MUST BE DASD IF RELATIVE FILE
! 2. MRS CANT BE 0 IF RELATIVE FILE
! 3. DEVICE MUST BE DASD ( THIS IS A TEMPORARY RESTRICTION FOR VERSION 1)
!
! ALL FILES:
! 1. UNUSED ATTRIBUTES MUST BE ZERO
! 2. VARIOUS VALUES MUST BE WITHIN PROPER RANGE
! 3. RECORD FORMAT MUST AGREE WITH THE FILE ORGANIZATION
!
!
GLOBAL ROUTINE FERROR =
BEGIN
LOCAL
TEMP;
TRACE ( 'FERRORS' );
%([ MAKE SURE THE RECORD FORMAT AGREES WITH THE ORGANIZATION ])%
IF ( ( STREAM ) OR ( SEQUENCED ) )
AND
( NOT ASCIIFILE )
THEN RETURNSTATUS ( ER$RFM ); ! MUST BE SEQ FILE FOR ASCII/LSA
%([ CHECK ASCII FILE ERRORS ])%
IF ASCIIFILE
THEN
BEGIN
IF .FAB [ FABBSZ ] ISNT ASCIIBYTESIZE THEN RETURNSTATUS ( ER$BSZ ); ! CHECK BYTE SIZE
IF BLOCKED THEN RETURNSTATUS ( ER$RAT ); ! RECORDS MUST SPAN PAGES
IF ( ( ( .FAB [ FABFAC ] AND .FAB [ FABSHR ] AND AXPUT ) ISON ) AND DASD ) 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 ] IS ZERO
THEN
BEGIN
IF RELFILE OR FIXEDLENGTH THEN RETURNSTATUS ( ER$MRS )
END;
IF NOT DASD THEN RETURNSTATUS ( ER$DEV ); ! MUST BE A DISK FILE
END; %( OF RMS-FILE CHECKS )%
%([ CHECK VARIOUS PARAMETERS ])%
IF FILEORG GTR ORGMAX THEN RETURNSTATUS ( ER$ORG ); ! CHECK FILE ORGANIZATION VALUE
IF ( .FAB [ FABBSZ ] GTR 36 ) OR ( .FAB [ FABBSZ ] IS ZERO )
THEN
RETURNSTATUS ( ER$BSZ ); ! CHECK BYTE SIZE
%([ FOR FUTURE COMPATIBILITY, MAKE SURE THAT THE UNSED
ROP BITS ARE NOT SET ])%
IF ( .FAB [ FABRAT ] AND RATUNUSED ) ISNT ZERO
THEN RETURNSTATUS ( ER$RAT ); ! CHECK UNDEFINED RAT BITS
IF .FAB [ FABRFM ] GTR RFMMAX THEN RETURNSTATUS ( ER$RFM ); ! CHECK RECORD FORMAT
IF FILEACCESS IS ZERO THEN RETURNSTATUS ( ER$FAC ); ! DONT ALLOW A NULL FAC
GOODRETURN
END; %( OF FERROR )%
! OABORT
! ======
! THIS ROUTINE PROCESSES THE ABORTING OF AN $OPEN OR $CREATE MACRO
! 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.
! INPUT:
! FLAGS FOR ABORTING (IN GLOBAL OAFLAGS):
! ABRUNLOCK - UNLOCK FILE
! ABRCLOSE - CLOSE FILE
! ABRFST - RELEASE FILESTATUS TABLE
! ABRPLOGPAGE - RELEASE THE FREE PAGE USED FOR PROLOGUE
! ABRADB - RELEASE THE AREA DESCRIPTOR BLOCK
! VALUE TO PUT IN USRSTS OR DIRECTIVE THAT CALL WAS FROM USRRET
! OUTPUT:
! <NONE>
GLOBAL ROUTINE OABORT ( ERRORCODE ): exitsub NOVALUE =
BEGIN
ARGUMENT (ERRORCODE,VALUE);
LOCAL
FLAGS,
TEMP;
MAP
TEMP: POINTER;
TRACE ( 'OABORT' );
FLAGS = .OAFLAGS; !USE LOCAL SO
OAFLAGS = ZERO; !...AVOID POSSIB OF RECURS ERR LOOP
%([ UNLOCK FILE RESOURCES IF LOCKED ])%
IF ( .FLAGS AND ABRUNLOCK ) ISON
THEN CALLFILEQ ( PCI ( DEQCALL ) , PCI ( DEQDR ));
%([ RELEASE CORE FOR FILE PROLOGUE TABLE ])%
%([ *NOTE THAT THIS PAGE MUST BE UNMAPPED BEFORE THE FILE IS CLOSED* ])%
IF ( ( .FLAGS AND ABRPLOGPAGE ) ISON )
THEN CALLPPAGE ( GCI ( PLOGPAGE ), PCI ( 1 ), PCI ( TRUE ) );
%([ CLOSE FILE ])%
IF ( .FLAGS AND ABRCLOSE ) ISON
THEN BEGIN
$CALL (ABORTFILE, .USERJFN, .FAB); ! USER JFN AND ADDRESS OF FAB
END;
%([ RELEASE CORE FOR FILE-STATUS TABLE ])%
IF ( ( .FLAGS AND ABRFST ) ISON )
THEN
BEGIN
%([ FIRST, WE MUST RELEASE ALL KEY DESCRIPTORS
FOR THIS FILE. FOR NON-INDEXED FILES, THERE
WONT BE ANY KEY DESCRIPTORS. AND, 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. ])%
%IF INDX %THEN
CALLUNDOKDBS; ! FLUSH ALL KDBS
%FI
TEMP = .FST [ BLOCKLENGTH ];
CALLPMEM ( LCI ( TEMP ), RGCI ( FST ) )
END; %(OF IF ABRFST IS ON)%
%([ RELEASE CORE FOR AREA DESCRIPTOR BLOCK ])%
IF ( ( .FLAGS AND ABRADB ) ISON )
THEN
BEGIN
TEMP = .ADB [ BLOCKLENGTH ]; ! GET LENGTH OF FST
CALLPMEM ( LCI ( TEMP ), RGCI ( ADB ) ) ! RELEASE CORE
END; %(OF IF ABRADB IS ON)%
IF .ERRORCODE EQL 0 THEN RETURN; !CALLED FROM USEREXIT
USRSTS = .ERRORCODE; ! STORE ERROR CODE
USEXITERR
END; %( OF OABORT ROUTINE )%
! CHECKXAB
! ========
! THIS ROUTINE SCANS THE XAB'S OF THE USER ON A $CREATE.
! IT CHECKS THE FOLLOWING THINGS:
! 1) BLOCK-TYPE
! 2) XAB COD-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 XAB'S
! INPUT:
! <NONE>
! OUTPUT:
! TRUE: OK
! FALSE:
! <ERROR CODE STORED IN USRSTS>
! GLOBALS USED:
! <NONE>
GLOBAL ROUTINE CHECKXAB =
BEGIN
%IF INDX %THEN
REGISTER
XABPTR; ! POINTER TO THE USER XAB
EXTERNAL
DTPTABLE; ! KEY DATA-TYPE CHARACTERISTICS TABLE
MAP
DTPTABLE: FORMAT;
LOCAL
TEMP,
KRFCOUNT, ! COUNTER USED TO INSURE KRF'S ARE IN ORDER
TOTALSIZE, ! ACCUMULATOR
KEYBYTESIZE, ! BYTE SIZE OF THE KEY STRING
AIDCOUNT, ! COUNT FOR THE SEQUENCING OF AID'S
KSDPTR; ! POINTER TO KEY SEGMENT DESCRIPTOR
MAP
XABPTR: POINTER,
KSDPTR: POINTER;
%([*** DONT COMPILE FOR VERSION 1***])%
TRACE ('CHECKXAB');
%([ GET THE START OF THE XAB CHAIN ])%
XABPTR = .FAB [ FABXAB ]; ! FETCH POINTER FROM FAB
%([ INIT THE COUNTER OF THE CURRENT VALUE OF THE KRF ])%
KRFCOUNT = ZERO;
AIDCOUNT = 1; ! USE DEFAULT AREA TO START
%([ WE MUST FIRST FIND THE AREA XABS AND CHECK THEM. THEN,
WE WILL SCAN FOR THE KEY XAB'S LATER. ])%
WHILE .XABPTR ISNT ZERO
DO
BEGIN
USRSTV = .XABPTR; ! SAVE ADDRESS OF BAD XAB
IF .XABPTR [ BLOCKTYPE ] ISNT XABCODE ! IS THIS AN XAB?
THEN RETURNSTATUS (ER$XAB); ! NO
IF .XABPTR [ XABCOD ] GTR MAXCOD ! VALID COD FIELD?
THEN RETURNSTATUS (ER$COD); ! NO
TEMP = .XABPTR [ XABNXT ]; ! GET NEXT XAB ADDRESS
IF ( .TEMP ISNT ZERO )
AND
( .TEMP LEQ MINUSERBUFF )
THEN RETURNSTATUS (ER$NXT); ! BAD NEXT ADDRESS
IF .XABPTR [ XABCOD ] IS CODAREA
THEN
BEGIN
%([ CHECK THE SIZE OF THIS XAB ])%
IF .XABPTR [ BLOCKLENGTH ] ISNT AREAXABSIZE THEN RETURNSTATUS (ER$BLN);
IF .XABPTR [ XABAID ] ISNT .AIDCOUNT THEN RETURNSTATUS (ER$AID);
IF ( .XABPTR [ XABBKZ ] GTR MAXBKZ )
OR
( .XABPTR [ XABBKZ ] IS ZERO )
THEN RETURNSTATUS (ER$BKZ); ! CHECK BUCKET SIZE
AIDCOUNT = .AIDCOUNT + 1
END; %(OF IF THIS IS AN AREA XAB)%
XABPTR = .XABPTR [ XABNXT ] ! GO TO NEXT XAB
END; %(OF WHILE .XABPTR ISNT ZERO)%
%([ NOW, WE WILL START ALL OVER AGAIN AND SEARCH FOR KEY XAB'S ])%
XABPTR = .FAB [ FABXAB ]; ! GET XAB CHAIN POINTER
WHILE .XABPTR ISNT ZERO
DO
BEGIN
USRSTV = .XABPTR; ! SAVE ADDRESS OF BAD XAB
IF .XABPTR [ XABCOD ] IS CODKEY
THEN %(THIS IS A KEY DEFINITION XAB)%
BEGIN
%([ CHECK THE SIZE OF THE XAB ])%
IF .XABPTR [ BLOCKLENGTH ] ISNT KEYXABSIZE THEN RETURNSTATUS (ER$BLN);
%([ CHECK THE DATA-TYPE OF THIS KEY ])%
IF .XABPTR [ XABDTP ] GTR MAXDTP
THEN RETURNSTATUS (ER$DTP);
%([ CHECK THAT THE KEY OF REFERENCES ARE IN ORDER ])%
IF .XABPTR [ XABREF ] ISNT .KRFCOUNT
THEN RETURNSTATUS (ER$REF);
%([ FIND THE BYTE SIZE FOR THIS KEY ])%
KEYBYTESIZE = .DTPTABLE [ .XABPTR [ XABDTP ], DTPBYTESIZE ];
IF .KEYBYTESIZE ISNT .FST [ FSTBSZ ]
THEN
RETURNSTATUS (ER$DTP);
%([ CHECK THAT THE FLAGS DONT CONTRADICT ])%
IF (( .XABPTR [ XABFLG ] AND FLGCHANGE ) ISON )
THEN %(KEYS CAN CHANGE...MAKE MORE CHECKS)%
BEGIN
IF .KRFCOUNT IS REFPRIMARY
THEN
RETURNSTATUS (ER$FLG)
END; %(OF FLAGS CHECKS)%
%([ CHECK THE INDEX AND DATA AREA NUMBER ])%
IF .XABPTR [ XABIAN ] GEQ .AIDCOUNT
THEN RETURNSTATUS (ER$IAN);
IF .XABPTR [ XABDAN ] GEQ .AIDCOUNT
THEN RETURNSTATUS (ER$DAN);
%([ SET UP POINTER TO KEY SEGMENT
DESCRIPTORS ])%
KSDPTR = .XABPTR + XABKSDOFFSET;
TOTALSIZE = ZERO;
INCR I FROM 0 TO MAXKEYSEGS-1
DO
TOTALSIZE = .TOTALSIZE
+ .KSDPTR [ .I, KEYSIZ ];
%([ CHECK THE LENGTH OF THE KEY ])%
IF ( .TOTALSIZE GTR MAXKEYSIZE )
OR
( .TOTALSIZE IS ZERO )
THEN RETURNSTATUS (ER$SIZ);
KRFCOUNT = .KRFCOUNT + 1 ! BUMP KRF TOTAL
END; %(OF IF THIS IS A KEY XAB)%
%([ CHECK THAT THIS WAS A VALID TYPE OF XAB ])%
IF .XABPTR [ XABCOD ] GTR MAXCOD THEN RETURNSTATUS (ER$COD);
IF .XABPTR [ BLOCKTYPE ] ISNT XABCODE
THEN RETURNSTATUS (ER$XAB);
%([ FETCH THE ADDRESS OF THE NEXT XAB IN THE CHAIN ])%
XABPTR = .XABPTR [ XABNXT ] ! NEXT BLOCK
END; %( OF WHILE .XABPTR ISNT ZERO )%
%([ NOW, CHECK THAT THERE ARE NOT TOO MANY KEY OR AREA XAB'S ])%
USRSTV = 0; !REMAINING ERRS NOT XAB SPECIFIC
IF .KRFCOUNT GTR MAXKEYS+1 THEN RETURNSTATUS (ER$IMX);
IF .AIDCOUNT GTR MAXAREAS THEN RETURNSTATUS (ER$IMX);
IF .KRFCOUNT IS ZERO THEN RETURNSTATUS (ER$NPK); ! NO PRIMARY KEY
%([ DID WE FIND AN ERROR DURING THIS ENTIRE PROCESS ])%
GOODRETURN;
%FI
END; %( OF CHECKXAB )%
! CLEANUP
! =======
! ROUTINE TO CLEAN UP SOME OPERATIONS AFTER A $PUT HAS FAILED.
! THIS ROUTINE MUST PERFORM THE FOLLOWING FUNCTIONS:
!
! A. UNLOCK THE INDEX STRUCTURE
! B. 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.
! INPUT:
! BKTDESC BUCKET DESCRIPTOR OF BUCKET TO RELEASE
! OUTPUT:
! <NONE>
! NOTE:
! 1. USRSTS MUST BE SET UP BY THE CALLER TO REFLECT THE
! CORRECT ERROR CODE.
! 2. THIS ROUTINE WILL RETURN OR NOT, DEPENDING UPON
! THE VALUE OF OAFLAGS.
! ROUTINES CALLED:
! LOCKIT
! PUTBKT
GLOBAL ROUTINE CLEANUP ( BKTDESC ): NOVALUE =
BEGIN
%IF INDX %THEN
ARGUMENT (BKTDESC,BASEADD); ! CURRENT BUCKET
MAP
BKTDESC: POINTER;
LOCAL
INDEXNUMBER; ! # OF CURRENT INDEX
TRACE ('CLEANUP');
%([ CHECK IF WE SHOULD UNLOCK THE INDEX ])%
IF INDEXLOCKED
THEN %(WE SHOULD)%
UNLOCKINDEX;
%([ SHOULD WE RELEASE THE CURRENT BUCKET ])%
IF NOT NULLBD ( BKTDESC )
THEN
CALLPUTBKT ( %(NO UPDATE)% PCI ( FALSE ),
%(BKT )% BPT ( BKTDESC ) );
%([ SHOULD WE RETURN TO THE CALLER OR TO THE USER? ])%
IF .OAFLAGS NEQ 0
THEN
RETURN
ELSE
USEXITERR;
%FI
END; %(OF CLEANUP)%
! REMOVRECORD
! ============
! 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 CLEAN-UP IN THAT IT IS MORE
! SPECIALIZED...IT MUST DELETE THE DATA RECORD FROM SOME
! OF THE SECONDARY INDEXES.
! SPECIFICALLY, THIS ROUTINE DOES THE FOLLOWING:
!
! 1. DELETE THE RECORD FROM ALL PREVIOUS SEC 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" BIT. THIS
! MEANS THAT THE UDR WILL STAY AROUND FOREVER IF ANY OF
! ITS SECONDARY INDEX ENTRIES CANNOT BE DELETED PROPERLY.
! INPUT:
! RECDESC RECORD DESCRIPTOR PACKET
! RFA RFA OF RECORD TO COMPRESS OUT
!
! DATABD BUCKET DESCRIPTOR OF DATA BUCKET
! SIBD BUCKET DESCRIPTOR OF SECONDARY INDEX (NOT USED NOW)
! OUTPUT:
! <NONE>
! NOTES:
! 1. KDB MUST POINT TO THE SEC INDEX KDB WHICH FAILED
! 2. THE ERROR CODE MUST ALREADY BE SET UP IN USRSTS
! 3. *****THIS ROUTINE EXITS DIRECTLY TO THE USER*****
GLOBAL ROUTINE REMOVRECORD ( RECDESC, DATABD ):NOVALUE =
BEGIN
%IF INDX %THEN
ARGUMENT (RECDESC,BASEADD); ! REC DESCRIPTOR
ARGUMENT (DATABD,BASEADD); ! DATA BUCKET
MAP
RECDESC: POINTER,
DATABD: POINTER;
LABEL FLUSHSIDR;
LABEL SIDRLOOP; ! LOOP FOR ALL SIDR RECORD
LOCAL
FAILKDBADDRESS, ! ADDRESS OF BAD KDB
OURBUFFER: FORMATS[ MAXKSZW ], ! USE AS TEMP BUFFER
USERRECORDPTR: POINTER, ! PTR TO USER DATA RECORD
SAVEDSTATUS, ! SAVED STATUS CODE
SAVEDERRORCODE, ! ERROR CODE ON ENTRY
FIXSIDRFLAG, ! TRUE IF ALL SIDR'S DELETED
SAVEDRFA, ! REMEMBER THE RFA OF UDR
SIZEOFTHISRCRD, ! FOR COMPRESSIONG
AMOUNTTOMOVE;
EXTERNAL ROUTINE
LOCKIT, ! LOCKING ROUTINE
DELUDR; ! SQUEEZE A UDR
REGISTER
TEMPAC,
BKTPTR: POINTER, ! PTR TO DATA BUCKET
UDRPTR: POINTER; ! PTR TO USER DATA RECORD
TRACE ('REMOVRECORD');
SAVEDERRORCODE = .USRSTS; ! SAVE THE PROPER CODE
%([ SAVE THE BAD KDB ADDRESS AND SET UP SOME MISC. THINGS ])%
FAILKDBADDRESS = .KDB;
USERRECORDPTR = .RAB [ RABRBF ];
RECDESC [ RDUSERPTR ] = OURBUFFER; ! ADDR OF KEY
%([ LOOP OVER ALL KDB'S AND DELETE THE RECORD IN THAT INDEX ])%
KDB = .FST [ FSTKDB ]; ! PRIMARY INDEX
KDB = .KDB [ KDBNXT ]; ! FIRST SEC INDEX
IF .KDB [ BLOCKTYPE ] ISNT KDBCODE THEN RMSBUG ( MSGKDB );
FIXSIDRFLAG = TRUE; ! ASSUME WE SUCCEED
%([ THIS IS THE LOOP ])%
SIDRLOOP:BEGIN
UNTIL .KDB IS .FAILKDBADDRESS
DO
BEGIN
%([ ONLY DELETE THE RECORD IF IT WAS INSERTED ])%
IF .RAB [ RABRSZ ] GEQ .KDB [ KDBMINRSZ ]
%(AND)%
%(THIS IS NOT THE NULL KEY VALUE)%
THEN
FLUSHSIDR: BEGIN
%([ MOVE THE SEC KEY INTO A TEMP BUFFER ])%
CALLMOVEKEY ( %(FROM)% LPT ( USERRECORDPTR ),
%(TO)% LCT ( OURBUFFER ) );
%([ SET UP THE KEY SIZE ])%
RECDESC [ RDUSERSIZE ] = .KDB [ KDBKSZ ];
%([ DELETE RECORD FROM SEC INDEX ])%
IF CALLDELSIDR ( BPT ( RECDESC ) ) IS FALSE
THEN
LEAVE SIDRLOOP WITH ( FIXSIDRFLAG=FALSE)
END; %(OF IF KEY WAS INSERTED INTO INDEX)%
%([ ADVANCE TO NEXT KDB ])%
KDB = .KDB [ KDBNXT ]
END; %(OF UNTIL KDB IS FAILKDBADDRESS)%
END; %(OF SIDRLOOP )%
%([ NOW, GO BACK AND LOCATE THE USER DATA RECORD ])%
KDB = .FST [ FSTKDB ]; ! SET PRIMARY KEY
RECDESC [ RDRECPTR ] = ZERO; ! START AT TOP
RECDESC [ RDRFA ] = .RECDESC [ RDRRV ]; ! SEARCH FOR NEW UDR
!+ !A55
! Locate the user data record with POSRFA, which will !A55
! search for the newly inserted record by RFA, which was !A55
! just placed in RECDESC [ RDRFA ]. SDATABKT was !A55
! originally used here, but when the new record went into a !A55
! separate bucket on a bucket split, SDATABKT would do an !A55
! ID search of the current bucket and the wrong UDR would !A55
! be deleted by REMOVRECORD. !A55
!- !A55
IF CALLPOSRFA ( %(RD)% BPT ( RECDESC ), !M55
%(BKT)% BPT ( DATABD )) IS FALSE
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 ISNT FALSE
THEN %(WE CAN SQUEEZE)%
CALLDELUDR ( %(RD)% BPT ( RECDESC ),
%(BKT)% BPT ( DATABD ),
%(LOCK)% PCI ( TRUE ) )
ELSE %(WE CAN ONLY 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) ])%
CALLPUTBKT ( %(UPDATE)% PCI ( TRUE ),
%(BKT)% BPT ( DATABD ) );
%([ UNLOCK THE FILE INDEX STRUCTURE, IF IT WAS LOCKED ])%
IF INDEXLOCKED THEN UNLOCKINDEX;
%([ ***EXIT TO USER*** ])%
USRSTS = .SAVEDERRORCODE; ! RESTORE CORRECT ERROR CODE
USEXITERR;
%FI
END; %(OF REMOVRECORD)%
! MAPCODES
! ========
! ROUTINE TO PERFORM 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 CODES 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-n !
! !-------------------------------------!
! ! 0 !
! !-------------------------------------!
! INPUT:
! SYSTEMCODE CODE RETURNED BY TOPS-20
! DEFAULTCODE RMS-20 ERROR CODE TO BE USED BY DEFAULT
! MAPTABLE ADDRESS OF ERROR MAPPING TABLE
! OUTPUT:
! <NO STATUS RETURNED>
! NOTES:
!
! 1. THE SETTING OF "OAFLAGS" DETERMINES IF THIS ROUTINE
! EXITS TO THE CALLER OR DIRECTLY TO THE USER.
! ROUTINES CALLES:
! <NONE>
GLOBAL ROUTINE MAPCODES ( SYSTEMCODE, DEFAULTCODE, MAPTABLE ): NOVALUE =
BEGIN
ARGUMENT (SYSTEMCODE,VALUE); ! TOPS-20 CODE
ARGUMENT (DEFAULTCODE,VALUE); ! DEFAULT RMS CODE
ARGUMENT (MAPTABLE,BASEADD); ! ADDR OF MAP TABLE
MAP
MAPTABLE: POINTER;
REGISTER
INDEX, ! USED TO INDEX INTO TABLE
TABLEPTR: POINTER; ! PTR TO MAPPING TABLE
TRACE ('MAPCODES');
%([ SET UP THE DEFAULT RMS-20 ERROR CODE IN USER STS FIELD ])%
USRSTS = .DEFAULTCODE;
USRSTV = .SYSTEMCODE; ! SAVE SYSTEM CODE
%([ INITIALIZE INDEX VARIABLE ])%
INDEX = ZERO;
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 [ .INDEX, WRD ] IS 0
DO
BEGIN
%([ CHECK IF THIS ERROR CODE IS IN TABLE ])%
IF .TABLEPTR [ .INDEX, EMTSYSCODE ] IS .SYSTEMCODE
THEN %(WE FOUND THE ERROR CODE)%
(USRSTS = .TABLEPTR [ .INDEX , EMTRMSCODE ]; EXITLOOP);
%([ BUMP THE TABLE INDEX ])%
INC ( INDEX, SIZEOFEMTENTRY )
END; %(OF UNTIL WE REACH THE END OF TABLE)%
%([ RETURN TO USER OR CALLER ])%
USEXITERR;
END; %(OF MAPCODES)%
END
ELUDOM