Trailing-Edge
-
PDP-10 Archives
-
decuslib10-08
-
43,50512/acct.b36
There are no other files named acct.b36 in the archive.
MODULE ACCT=
!Routine(s) to create FACT file entries
BEGIN
!
! Conditional compilation
!
COMPILETIME FTDEBUG=%SWITCHES(DEBUG); !Do debugging code
!COMPILETIME FTIPC=(%VARIANT AND 4) NEQ 0;
!FTIPC set in library file
!
! Table of Contents
!
FORWARD ROUTINE
ACCT;
!
! LIBRARY & REQUIRE files
!
LIBRARY 'INTR';
LIBRARY 'DAPLIB';
THIS_IS [ACCT] VERSION[1] EDIT[3] DATE[20,JUN,78]
!
! Tell about conditionals
!
%IF FTIPC %THEN %INFORM('ACCT for IPC being built') %FI
!
! Field definitions
!
%( Following is the definition of the NETSPL FACT file entry.
All entries are SIXBIT except (#) BINARY or (NBS) NBS Date/time format
)%
FIELD ACCT_FIELDS = SET
DFF[ACCT$RECORDTYPE,FIRSTWORD,27,9,0], !(#) Record type
DFF[ACCT$JOBNUM,THISWORD,18,9,0], !(#)
DFF[ACCT$TTYNUM,THISWORD,6,12,0], !(#)
DFF[ACCT$ENTLEN,THISWORD,0,6,0], !(#) # of words in entry
DFF[ACCT$PPN,NEXTWORD,WRD], !(#) PPN of requestor
DFF[ACCT$DTM_FINISH,NEXTWORD,WRD], !(NBS)
%IF FTIPC %THEN
DFF[ACCT$CHARGE,MWORDS(3),WRD], !Charge info
%FI
%( The above field will be interpreted differently on charge accounting
systems from cost/task systems.
On charge accounting:
ACCT$CHARGE <-- Charge # (.GTCNO)
ACCT$JOBNAME <-- Batch job name (.GTCID)
On cost/task accounting
ACCT$CC <-- Cost center
ACCT$ACTIVITY <-- Activity code (up to 2 letters) "A" (alpha)
ACCT$PL <-- Product line "p" (numeric)
ACCT$PROJNUM <-- Project number "n" (numeric)
A DPJ # is: AApppnnnnn
Note that this is all stored in SIXBIT in the FACT file entry
)%
%IF FTIPC %THEN
DFF[ACCT$CC,%FIELDEXPAND(ACCT$CHARGE,0),12,24,0], !Cost center
DFF[ACCT$ACTIVITY,(%FIELDEXPAND(ACCT$CHARGE,0)+1),24,12,0], !Activity code
DFF[ACCT$PL,%FIELDEXPAND(ACCT$ACTIVITY,0),RH], !Product line
DFF[ACCT$PROJNUM,(%FIELDEXPAND(ACCT$ACTIVITY,0)+1),0,30,0], !Project number
%FI
DFF[ACCT$DISKIO,NEXTWORD,WRD], !(#) # of disk blocks r/w
%IF FTIPC %THEN
DFF[ACCT$JOBNAME,NEXTWORD,WRD], !Requestor's batch job name
%FI
DFF[ACCT$FUNCTION,NEXTWORD,LH], !Function requested
DFF[ACCT$PRIORITY,THISWORD,RH], !(#) Request priority
DFF[ACCT$DISPOS,NEXTWORD,LH], !Disposition
DFF[ACCT$OPTIONS,THISWORD,RH], !Options requested
DFF[ACCT$DTM_QUEUE,NEXTWORD,WRD], !(NBS) Date & time queued
DFF[ACCT$DTM_START,NEXTWORD,WRD], !(NBS) Date & time started
%IF FTIPC %THEN
DFF[ACCT$LNODEID,NEXTWORD,WRD], !Our nodeid
%FI
DFF[ACCT$LPPN,NEXTWORD,WRD], !(#) Local file ppn
DFF[ACCT$LDEVICE,NEXTWORD,WRD], !Local device
DFF[ACCT$LNAME,NEXTWORD,WRD], !Local filename
DFF[ACCT$LEXTENSION,NEXTWORD,LH], !Local extension
DFF[ACCT$SEQUENCE,THISWORD,RH], !(#) Sequence # of request
DFF[ACCT$NODEID,NEXTWORD,WRD], !Remote nodeid
DFF[ACCT$RNODEID,%FIELDEXPAND(ACCT$NODEID)], !Synonym
DFF[ACCT$RFILE,MWORDS(6),WRD], !Remote filespec
DFF[ACCT$PACKETS,NEXTWORD,WRD] !(#) # of packets transmitted/received
TES;
DLIT(ACCT_LEN,NEXTWORD); !Length of all this
!
! Externals
!
EXTERNAL ROUTINE
NODENN, !Convert a node # into a node name
GETLNN, !Get our node number
UDT; !Get the current time in universal date-time format
!
! Literals
!
LITERAL NET_ACCT_TYPE=333; !Record type for NETSPL FACT file entries
LITERAL DISKIO_FUDGE=1; !We assume 1 block for reading ACCESS.USR
!
! Macros
!
MACRO PREFIX='ACT'%; !For MSG macro
MACRO SXC(CHAR)=(%C %STRING(CHAR) - %O'40' ) %; !1 char of SIXBIT
MACRO SX(STR)=(%SIXBIT %STRING(' ',STR)) %; !Half a word of SIXBIT
MACRO DO_ACCT_ENTRY(BLK)=
BEGIN
EXTERNAL ROUTINE SCALLI;
LITERAL _FACT=3, DAEMON_=%O'102';
BLK=_FACT;
IF SCALLI(DAEMON_,(XWD((ACCT_LEN+1),BLK))) EQL 0 THEN
IFMSG(WARN,(WRN('Accounting entry failure')));
END%;
!
! Routines
!
GLOBAL ROUTINE ACCT(NB)=
!Routine to create a FACT file entry for a successful transfer
BEGIN
MAP NB: REF NDB;
BIND EQ=.NB[NDB$EQ]: QSR_EQ, !Request that created us
FB=.NB[NDB$FB]: FILE_BLOCK; !Local file block
!The following construct is required because we have to put a function
!code for the DAEMON UUO into the word before the actual fact file entry.
!This way the fields reflect the FACT file, not the argument block to DAEMON.
LOCAL AV: VECTOR[ACCT_LEN+1];
BIND AE=AV[1]: BLOCK[ACCT_LEN] FIELD(ACCT_FIELDS); !Our accounting entry
CLEARV(AV);
IF EQ EQL 0 THEN
BEGIN
DEBUGMSG(WRN('No EQ, Accounting entry not made'));
RETURN !No queue request, give up!!
END;
IF FB EQL 0 THEN
BEGIN
DEBUGMSG(WRN('No FB, Accounting entry not made'));
RETURN !Can't find file block
END;
AE[ACCT$DTM_FINISH]=UDT(); !Finished it now
!AE[ACCT$DTM_START]=.NB[NDB$DTM_START];
!AE[ACCT$DTM_QUEUE]=.EQ[QSR$EQ_?????];
AE[ACCT$PPN]=.FB[FILE$ALIAS]; !Requestor
%IF %DECLARED(QSR$EQ_CHARGE) %THEN !Probably for IPC
AE[ACCT$CHARGE]=.EQ[QSR$EQ_CHARGE];
%FI
!AE[ACCT$JOBNAME]=.EQ[QSR$EQ_JOBNAME]; !Where do we get this??
AE[ACCT$LPPN]=.FB[FILE$PPN]; !Local filespec now
AE[ACCT$LDEVICE]=.FB[FILE$DEVICE];
AE[ACCT$LNAME]=.FB[FILE$NAME];
AE[ACCT$LEXTENSION]=.FB[FILE$EXTENSION];
AE[ACCT$DISKIO]=(.NB[NDB$LOG_FB] NEQ 0)+ !1 block for user log file if any
((.FB[FILE$READS]+.FB[FILE$WRITES])*2)+DISKIO_FUDGE;
!Whatever we read, the other NETSPL must have written & visaversa
!The fudge factor is for ACCESS.USR on the remote system
AE[ACCT$PACKETS]=.NB[FILE$READS]+.NB[FILE$WRITES]; !Network packets
AE[ACCT$RNODEID]=.NB[NDB$NODEID]; !Foreign NODEID
%IF %DECLARED(ACCT$LNODEID)
%THEN AE[ACCT$LNODEID]=NODENN(GETLNN()); !Our own NODEID
%FI
AE[ACCT$SEQUENCE]=.EQ[QSR$EQ_SEQ]; !Sequence #
AE[ACCT$PRIORITY]=.EQ[QSR$EQ_PRIOR]; !Priority
AE[ACCT$JOBNUM]=.EQ[QSR$EQ_RJOB]; !Requestor's job #
AE[ACCT$FUNCTION]=(
CASE .NB[NDB$ACCFUNC] FROM 1 TO ACC$EXE OF SET
[ACC$OPEN]: SX(RET);
[ACC$CREATE]: SX(TRA);
[ACC$RENAME]: SX(REN);
[ACC$ERASE]: SX(DEL); !Delete
[ACC$LIST]: SX(DIR); !List directory
[ACC$CMD]: SX(BAT); !Submit file as batch job
[ACC$EXE]: SX(EXE); !Execute a batch job
[INRANGE,OUTRANGE]:
BEGIN
DEBUGMSG(WRN('Unimplemented function, no accounting was done'));
RETURN
END;
TES);
!Options
BEGIN
LOCAL PTR;
PTR=CH$PTR(AE[ACCT$OPTIONS],0,6); !SIXBIT byte pointer
IF .NB[NDB$LOG_FB] NEQ 0 THEN CH$WCHAR_A(SXC(L),PTR);
!Further options may follow. If more than 3, make sure
!we don't overflow. Put the most important ones first
!in case more than 3 appear at once.
END;
!Remote filespec. Convert to long SIXBIT string (truncate after 36 chars)
BEGIN
LOCAL PTR;
LOCAL FPTR;
PTR=CH$PTR(AE[ACCT$RFILE],0,6); !SIXBIT byte pointer
FPTR=CH$PTR(NB[NDB$REMOTEFILE]);
!The following has the possibly undesirable property that
!the remote filename will be arbitrarily truncated after 36 characters.
!so FOOBARBLETCH:<CPL-SOURCES-FIELD-TEST>OLD-VERSION-OF-TFILE4.MACRO
!becomes FOOBARBLETCH:<CPL-SOURCES-FIELD-TES
!and the filename loses entirely.
DECR I FROM 36 TO 1 DO
BEGIN
LOCAL C;
C=CH$RCHAR_A(FPTR); !Convert & copy
IF .C EQL 0 THEN EXITLOOP; !Leave if end of string
CH$WCHAR_A(.C-%O'40',PTR);
END
END;
!Now the record type (canned) and the length
AE[ACCT$ENTLEN]=ACCT_LEN; !This is generated automaticly above
AE[ACCT$RECORDTYPE]=NET_ACCT_TYPE;
!Now send it off
DO_ACCT_ENTRY(AV);
END; !ACCT
END ELUDOM