Google
 

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