!TITLE Procedures for manipulating Name-Number Tables
!DUMPNNT lists the entries that are in use
!
!CLEARNNT sets a NNT to zero. It can (will) be re-created
! automatically at the next CCK
!
!STATUSNNT analyses a NNT and computes a histogram of the path
! lengths to reach each name
!
!OPTNNT saves the current NNT in a file N#NTf where f is the
! fsys number. Re-orders the entries in an optimum way
!
!RESTORENNT returns the contents N#NTf to the NNT
!>
RECORDFORMAT NNF(STRING (6) USER, BYTEINTEGER KB, TAG, MARKER,
HALFINTEGER INDNO)
CONSTINTEGER NNTTOP= 1364
OWNRECORD (NNF) ARRAY NEWNNT(0:NNTTOP)
OWNRECORD (NNF) ARRAYFORMAT NNAF(0:NNTTOP)
CONSTSTRING (5)TFILE = "N#NT"
!
RECORDFORMAT DATAF(INTEGER START, BITSIZE, NNTSTART, NNTSIZE,
NNTTOP, NNTHASH, INDEXSTART, FILESTART, END)
RECORDFORMAT FF(INTEGER SD, PD, FD, S,
S1, S2, SNO, RESTORES,
STRING (6)OWNER, BYTEINTEGER SIZE, STRING (11)NAME)
!
!
!
EXTERNALSTRINGFNSPEC DERRS(INTEGER N)
! %EXTERNALINTEGERFNSPEC DERROR(%STRINGNAME TXT)
EXTERNALINTEGERFNSPEC DLOWERACR(INTEGER ACR)
EXTERNALINTEGERFNSPEC DBITMAP2(INTEGERNAME LO, HI, INTEGER FSYS)
EXTERNALINTEGERFNSPEC DNINDA(INTEGER FSYS, INDNO, INTEGERNAME INDAD)
EXTERNALINTEGERFNSPEC FBASE(INTEGERNAME LO, HI, INTEGER FSYS)
SYSTEMSTRINGFNSPEC HTOS(INTEGER VALUE, PALCES)
SYSTEMSTRINGFNSPEC ITOS(INTEGER I)
EXTERNALROUTINESPEC PROMPT(STRING (15) S)
EXTERNALSTRINGFNSPEC DATE
EXTERNALSTRINGFNSPEC TIME
INTEGERFN STOI2(STRING (255) S, INTEGERNAME I2)
STRING (63) P
INTEGER TOTAL, SIGN, AD, I, J, HEX
!MON MON(1) = MON(1) + 1
HEX = 0; TOTAL = 0; SIGN = 1
AD = ADDR(P)
A: IF S -> (" ").S THEN -> A; !CHOP LEADING SPACES
IF S -> ("-").S THEN SIGN = -1
IF S -> ("X").S THEN HEX = 1 AND -> A
P = S
UNLESS S -> P.(" ").S THEN S = ""
I = 1
WHILE I <= BYTEINTEGER(AD) CYCLE
J = BYTE INTEGER(I+AD)
-> FAULT UNLESS '0' <= J <= '9' OR (HEX # 0 C
AND 'A' <= J <= 'F')
IF HEX = 0 THEN TOTAL = 10*TOTAL C
ELSE TOTAL = TOTAL<<4+9*J>>6
TOTAL = TOTAL+J&15; I = I+1
REPEAT
IF HEX # 0 AND I > 9 THEN -> FAULT
IF I > 1 THEN I2 = SIGN*TOTAL AND RESULT = 0
FAULT:
I2 = 0
RESULT = 1
END ; ! STOI2
!
!-----------------------------------------------------------------------
!
!-----------------------------------------------------------------------
!
!
!
ROUTINE RSTRG(STRINGNAME S)
INTEGER I
S = ""
CYCLE
READSYMBOL(I)
RETURN IF I = NL
S = S . TOSTRING(I)
REPEAT
END
!
!
!
ROUTINE RDINT(INTEGERNAME N)
STRING (63)S
N = -1
CYCLE
RSTRG(S)
RETURN IF STOI2(S, N) = 0
REPEAT
END
!
EXTERNALINTEGERFNSPEC DDISCONNECT(STRING (6) USER, STRING (11) FILE,
INTEGER FSYS, DESTROY)
EXTERNALINTEGERFNSPEC DCONNECT(STRING (6) USER, STRING (11) FILE,
INTEGER FSYS, MODE, APF, INTEGERNAME SEG, GAP)
EXTERNALINTEGERFNSPEC DCREATE(STRING (6) USER, STRING (11) FILE,
INTEGER FSYS, NKB, TYPE)
SYSTEMROUTINESPEC MOVE(INTEGER LEN, FROM, TO)
SYSTEMROUTINESPEC FILL(INTEGER LEN, FROM, PATTERN)
!
!
!
ROUTINE WS(STRING (255) S)
PRINTSTRING(S)
NEWLINE
END ; ! WS
!
!
!
ROUTINE WSN(STRING (255)S, INTEGER N)
PRINTSTRING(S)
WRITE(N, 1)
NEWLINE
END ; ! WSN
!
!
!
INTEGERFN FBASE2(INTEGER FSYS, ADR)
!
! This returns the characteristics of an on-line disc in a record
! of format DISCDATAF at address ADR
INTEGER J, LOB, HIB, TYPE, K
RECORD (DATAF) NAME DATA
CONSTINTEGER TOPTYPE= 5
CONSTINTEGERARRAY BITSIZE(1:TOP TYPE)= X'1000'(2), X'2000'(2), X'5000'
CONSTINTEGERARRAY NNTSTART(1:TOP TYPE)= X'7000'(4), X'A000'
CONSTINTEGERARRAY NNTSIZE(1:TOP TYPE)= X'4000'(4), X'1FF8'
CONSTINTEGERARRAY NNTTOP(1:TOP TYPE)= 1364(4), 681
CONSTINTEGERARRAY NNTHASH(1:TOP TYPE)= 1361(4), 667
CONSTBYTEARRAY INDEXSTART(1:TOP TYPE)= 12(5)
CONSTINTEGERARRAY FILESTART(1:TOP TYPE)= 1024(5)
CONSTINTEGERARRAY HI(1:TOP TYPE)= X'3F1F', X'59F3', X'8F6F',
X'B3E7', X'24797'
J = FBASE(LOB, HIB, FSYS)
RESULT = J UNLESS J = 0
!
TYPE = - 1
CYCLE K = 1, 1, TOP TYPE
TYPE = K ANDEXITIF HIB = HI(K)
REPEAT
RESULT = 8 IF TYPE < 0
!
DATA == RECORD(ADR)
!
DATA_START = LOB
DATA_BITSIZE = BITSIZE(TYPE)
DATA_NNTSTART = NNTSTART(TYPE)
DATA_NNTSIZE = NNTSIZE(TYPE)
DATA_NNTTOP = NNTTOP(TYPE)
DATA_NNTHASH = NNTHASH(TYPE)
DATA_INDEXSTART = INDEX START(TYPE)
DATA_FILESTART = FILE START(TYPE)
DATA_END = HIB
RESULT = 0
END ; ! FBASE2
!
!-----------------------------------------------------------------------
!
INTEGERFN HASH(STRING (6) USER, INTEGER NNTHASH)
INTEGER A, J, W
CONSTINTEGERARRAY P(1:6)=157,257,367,599, 467,709
A = ADDR(USER)
W = 0
CYCLE J = 1, 1, 6
W = W + (BYTEINTEGER(A + J) - 47) * P(J)
REPEAT
RESULT = W - (W // NNTHASH) * NNTHASH
END ; ! HASH
!
!
!
INTEGERFN INIT(INTEGERNAME FSYS, ANNT, RECORD (DATAF)NAME DATA)
INTEGER FLAG, LO, HI
PROMPT("Which FSYS? ")
RDINT(FSYS)
!
FLAG = FBASE2(FSYS, ADDR(DATA)); ! get characteristics of disc
->FAIL UNLESS FLAG = 0
!
FLAG = DBITMAP2(LO, HI, FSYS)
-> FAIL UNLESS FLAG = 0
ANNT = LO >> 18 << 18 + DATA_NNTSTART
FAIL:
RESULT = FLAG
END ; ! INIT
!
!
!
EXTERNALROUTINE DUMPNNT(STRING (255)S)
INTEGER FLAG, FSYS, ANNT, J
RECORD (DATAF)DATA
RECORD (NNF)ARRAYNAME NNT
FLAG = INIT(FSYS, ANNT, DATA)
-> FAIL UNLESS FLAG = 0
!
NNT == ARRAY(ANNT, NNAF)
!
CYCLE J = 0, 1, DATA_NNTTOP
IF LENGTH(NNT(J)_USER) = 6 START
WRITE(J, 4)
SPACE
PRINTSTRING(NNT(J)_USER)
WRITE(NNT(J)_KB, 3)
WRITE(NNT(J)_INDNO, 5)
PRINTSTRING(" (file index)") UNLESS NNT(J)_TAG = 0
NEWLINE
FINISH
REPEAT
FAIL:
WS(DERRS(FLAG))
END ; ! DUMPNNT
!
!
!
EXTERNALROUTINE OPTNNT(STRING (255) S)
INTEGER FLAG, I, NUSERS, PATH, NEWI, A, NNTTOP, ANNT, NNTHASH
INTEGER FSYS, SEG, GAP
RECORD (DATAF) DATA
RECORD (NNF) ARRAY AUX(0:1364)
RECORD (NNF) ARRAYNAME OLDNNT
STRING (11)FILE
A = 0; ! POSITION ON AUXTAB
NUSERS = 0
PATH = 0
!
FLAG = INIT(FSYS, ANNT, DATA)
-> FAIL UNLESS FLAG = 0
!
FILE = TFILE . ITOS(FSYS)
NNTTOP = DATA_NNTTOP
NNTHASH = DATA_NNTHASH
CYCLE I = 0, 1, NNTTOP; ! clear own array
NEWNNT(I) = 0
REPEAT
!
!
FLAG = DCREATE("", FILE, -1, 20, 0); ! big enough for a 4-page NNT and hdr
-> FAIL UNLESS FLAG = 0
!
SEG = 0
GAP = 0
FLAG = DCONNECT("", FILE, -1, 3, 0, SEG, GAP)
-> FAIL UNLESS FLAG = 0
!
OLDNNT == ARRAY(SEG<<18 + 4096, NNAF)
!
MOVE(DATA_NNTSIZE, ANNT, ADDR(OLDNNT(0)))
!
CYCLE I = 0, 1, NNTTOP
IF LENGTH(OLDNNT(I)_USER) = 6 START
NUSERS = NUSERS + 1
NEWI = HASH(OLDNNT(I)_USER, NNTHASH)
IF NEWNNT(NEWI)_USER = "" C
THEN NEWNNT(NEWI) = OLDNNT(I) C
ELSESTART
AUX(A) = OLDNNT(I)
A = A + 1
FINISH
FINISH
REPEAT
!
FLAG = DDISCONNECT("", FILE, -1, 0)
-> FAIL UNLESS FLAG = 0
!
WSN("No of users:", NUSERS)
WSN("No of clashes:", A)
!
WHILE A > 0 CYCLE
A = A - 1
NEWI = HASH(AUX(A)_USER, NNTHASH)
CYCLE
PATH = PATH + 1
NEWI = NEWI + 1
NEWI = 0 IF NEWI > NNTTOP
IF NEWNNT(NEWI)_USER = "" C
THEN NEWNNT(NEWI) = AUX(A) AND EXIT
REPEAT
REPEAT
WSN("Path length:", PATH)
!
FLAG = D LOWER ACR(2)
-> FAIL UNLESS FLAG = 0
!
MOVE(DATA_NNTSIZE, ADDR(NEWNNT(0)), ANNT)
FAIL:
! J = DERROR(TXT)
WS(DERRS(FLAG))
END ; ! OPTNNT
!
!
!
EXTERNALROUTINE RESTORE NNT(STRING (255)S)
INTEGER FLAG, FSYS, ANNT, SEG, GAP, J
STRING (11)FILE
RECORD (DATAF)DATA
FLAG = INIT(FSYS, ANNT, DATA)
-> FAIL UNLESS FLAG = 0
!
SEG = 0
GAP = 0
FILE = TFILE . ITOS(FSYS)
FLAG = DCONNECT("", FILE, -1, 1, 0, SEG, GAP)
-> FAIL UNLESS FLAG = 0
!
FLAG = DLOWERACR(2)
-> FAIL UNLESS FLAG = 0
!
MOVE(DATA_NNTSIZE, SEG<<18 + 4096, ANNT)
FAIL:
J = DDISCONNECT("", FILE, -1, 0)
WS(DERRS(FLAG))
END ; ! RESTORE NNT
!
!
!
EXTERNALROUTINE CLEAR NNT(STRING (255)S)
INTEGER FLAG, FSYS, ANNT
RECORD (DATAF)DATA
FLAG = INIT(FSYS, ANNT, DATA)
-> FAIL UNLESS FLAG = 0
!
FLAG = DLOWERACR(2)
-> FAIL UNLESS FLAG = 0
!
FILL(DATA_NNTSIZE, ANNT, 0)
FAIL:
WS(DERRS(FLAG))
END ; ! CLEAR NNT
!
!
!
EXTERNALROUTINE STATUSNNT(STRING (255) S)
INTEGER ANNT, NUSERS, P
RECORD (NNF) NAME NN
RECORD (NNF) ARRAYNAME NNT
INTEGER FLAG, I, J
INTEGER FSYS, PATH
INTEGERARRAY HISTO(0:8)
RECORD (DATAF) DATA
WS("STATUS at ".TIME." on ".DATE)
NUSERS = 0
PATH = 0
CYCLE J = 0, 1, 8
HISTO(J) = 0
REPEAT
!
FLAG = INIT(FSYS, ANNT, DATA)
-> FAIL UNLESS FLAG = 0
!
NNT == ARRAY(ANNT, NNAF)
!
CYCLE J = 0, 1, DATA_NNTTOP
NN == NNT(J)
IF LENGTH(NN_USER) = 6 START
NUSERS = NUSERS + 1
P = J - HASH(NN_USER, DATA_NNTHASH)
P = P + DATA_NNTTOP IF P < 0
PATH = PATH + P
!
HISTO(P) = HISTO(P) + 1 IF P <= 5
HISTO(6) = HISTO(6) + 1 IF 6 <= P <= 10
HISTO(7) = HISTO(7) + 1 IF 11 <= P <= 20
HISTO(8) = HISTO(8) + 1 IF P > 20
FINISH
REPEAT
WSN("No of users :", NUSERS)
WSN("Total path :", PATH)
PRINTSTRING("Average path:")
PRINT(PATH/NUSERS, 3, 2)
NEWLINE
WS("Path length histogram")
WS(" 0 1 2 3 4 5 6-10 11-20 >20")
CYCLE I = 0, 1, 8
WRITE(HISTO(I), 6)
REPEAT
NEWLINE
FAIL:
WS(DERRS(FLAG))
END ; ! STATUSNNT
!
!
!
EXTERNALROUTINE CLEAR EXTRA INDEX(STRING (255)S)
INTEGER J, FSYS, ANNT, INDNO, HI, P, INDAD
RECORD (DATAF)DATA
J = INIT(FSYS, ANNT, DATA)
-> FAIL UNLESS J = 0
!
INDNO = 256 << 2; ! first 1K after 'old' indexes
HI = DATA_FILESTART << 2 - 1; ! last
J = DLOWERACR(2)
-> FAIL UNLESS J = 0
CYCLE P = INDNO, 1, HI
J = DNINDA(FSYS, P, INDAD)
-> FAIL UNLESS J = 0
FILL(1024, INDAD, 0)
STRING(INDAD) = "NEVER"
REPEAT
FAIL:
WS(DERRS(J))
END ; ! CLEAR EXTRA INDEX
!
!
!
EXTERNALROUTINE CHECK EXTRA INDEX(STRING (255)S)
INTEGER J, FSYS, ANNT, INDNO, HI, P, K, INDAD, C
RECORD (DATAF)DATA
RECORD (FF)NAME F
J = INIT(FSYS, ANNT, DATA)
-> FAIL UNLESS J = 0
!
INDNO = 256 << 2
HI = DATA_FILESTART << 2 -1
C = 0
CYCLE P = INDNO, 1, HI
J = DNINDA(FSYS, P, INDAD)
-> FAIL UNLESS J = 0
F == RECORD(INDAD)
IF LENGTH(F_OWNER) = 6 AND 0 < LENGTH(F_NAME) < 12 START
C = C + 1
RETURN IF C > 20
PRINTSTRING(HTOS(P<<2+K, 3))
SPACE
PRINTSTRING(F_OWNER . " " . F_NAME . "
")
FINISH
REPEAT
FAIL:
WS(DERRS(J))
END ; ! CHECK EXTRA INDEX
!
!
!
EXTERNALROUTINE WRITE NEVERS(STRING (255)S)
INTEGER J, FSYS, ANNT, LO, HI, P, INDAD
RECORD (DATAF)DATA
J = INIT(FSYS, ANNT, DATA)
-> FAIL UNLESS J = 0
!
LO = 12 << 2
HI = 256 << 2 - 2
!
J = DLOWERACR(2)
-> FAIL UNLESS J = 0
!
CYCLE P = HI, -2, LO
J = DNINDA(FSYS, P, INDAD)
-> FAIL UNLESS J = 0
UNLESS STRING(INDAD) = "EMPTY" START
WSN("LAST NON EMPTY", P)
EXIT
FINISH
STRING(INDAD) = "NEVER"
REPEAT
FAIL:
WS(DERRS(J))
END ; ! WRITE NEVERS
ENDOFFILE