! This version differs from the standard only in its treatment of a 'full ! tape' condition - it stops rather than reuse an old tape. !FILE LAST CHANGED ON 11/02/83 ! ******************************************************************* ! * * ! * THE JOURNAL SYSTEM: PACKAGE A. * ! * THIS PACKAGE IS THE MANAGEMENT SECTION OF THE EMAS 2900 * ! * JOURNAL SYSTEM. * ! * * ! * DESIGNED AND WRITTEN BY JOHN HENSHALL * ! * * ! * JOHN MURISON VERSION: 015 * ! * * ! * * ! ******************************************************************* constinteger kent = 0, ercc = 1 constinteger journalsite = kent !********** SYSTEM ROUTINE SPECS recordformat rf(integer conad, filetype, datastart, dataend) systemroutinespec connect(string (31) file, integer mode, hole, project, record (rf)name r, integername flag) systemroutinespec destroy(string (31) s, integername flag) systemroutinespec disconnect( string (31) file, integername flag) systemroutinespec move(integer l, f, t) systemroutinespec outfile(string (31) s, integer size, hole, protection, integername conad, flag) systemroutinespec oper(integer operno, string (255) s) systemroutinespec sdisconnect(string (31) file c integer fsys, integername flag) !**********EXTERNAL ROUTINE SPECS. externalroutinespec cherish(string (255) s) externalroutinespec copy(string (255) s) externalroutinespec define(string (255) s) recordformat f rep b(integer dest, srce, byteinteger flag, string (6) file, string (15) output q) externalroutinespec dpoff(record (f rep b)name p) recordformat f parm(integer dest, srce, p1, p2, p3, p4, p5, p6) externalintegerfnspec exist(string (31) file) externalintegerfnspec dspool(record (f parm)name p, integer len, adr) externalroutinespec newpdfile(string (255) s) externalroutinespec journal analysis(string (255) s) externalroutinespec prompt(string (255) s) externalroutinespec rename(string (255) s) externalroutinespec readmag(integer chnl, addr, integername len, flag) externalroutinespec write tmmag(integer chnl, integername flag) externalroutinespec unload mag(integer chnl) externalroutinespec open mag(integer chnl, string (7) tsn) externalroutinespec write mag(integer chnl, addr, len, integername c flag) externalroutinespec skip mag(integer chnl, blocks) externalroutinespec skip tm mag(integer chnl, marks) externalroutinespec f skip tm mag(integer chnl, marks, integername flag) externalstringfnspec date externalroutinespec send(string (255) s) externalstringfnspec time !**********ROUTINE AND FUNCTION SPECS. routinespec identify index(string (*)name keyword, byteintegername c id char, data type, integername entry) routinespec line to atoms(integername word count, stringarrayname atom, byteintegerarrayname buff) routinespec master file failure(string (*)name file, integer flag) routinespec journal(string (255) s) routinespec new journal index(string (255) s) routinespec new journal tape(string (255) s) externalroutinespec journal backpass(string (255) s) externalroutinespec create jfile(string (11) name, integer cells, cellsize, headersize, integername conad, flag) externalroutinespec read prompt reply(string (*)name reply) externalintegerfnspec s to i(string (*)name s) externalintegerfnspec cyclic(integer from, direction) externalstringfnspec intostr(integer value) systemintegerfnspec pack date and time(string (8) date, time) systemintegerfnspec dt word(integer old form) externalintegerfnspec minutes between(integer from,to) systemstringfnspec unpack date(integer packed) systemstringfnspec unpack time(integer packed) systemintegerfnspec current packed dt externalintegerfnspec uinfi(integer entry) !**********RECORD FORMATS recordformat f chapter header(string (6) tape name, user name, string (15) file name, string (8) date, time, type, byteinteger spare0, spare1, spare2, integer chapter, epages, fsys, perms) recordformat f index entry(integer file id, starting, finishing, chapter, string (6) tape, byteinteger status) {24 bytes} recordformat f index list(byteinteger id char, data type, string (12) identity) {15 bytes} recordformat f parameters(string (4) lower file, upper file, string (12) keyword, analysis) recordformat f queue(string (15) name, halfintegerarray streams(0:15), string (7) default user, string (31) default delivery, integer default start, default priority, default time, default outlim, default forms, default mode, default copies, default rerun, length, head, max length, maxacr, q by, spare, amount) recordformat f tape cycle(string (6) tsn, integer age) !**********CONSTANT ARRAYS. conststring (3) array ocptimereq(0:16)= c "600", "600", "600", "420", "300", "300", "300", "600", "600", "600", "600", "600", "600", "600", "600", "600", "600" conststring (60) array journal status(0:4)= c "Failure occurred at undefined point!!", "Failure occurred during file collection from Spooler", "Last run opted out of tape dump", "Failure occurred whilst dumping files to tape", "Next run is clear to rerun tape dump" conststring (9) array system keyword(0:9)= c "MAINLOG", "VOLUMS", "SPOOLR", "ACCOUNTS", "DIRECT", "BACK&ARCH", "UPDATES", "MAILER", "SPARE3", "SPARE4" !THE SYSTEM INDICES RECOGNITION KEYWORDS. !**********CONSTANTS. constinteger block = 4096 !BYTES IN EPAGE. constinteger index top = 9999 !THE PHYSICAL TOP OF AN INDEX. constinteger system indices = 9 constinteger used system indices = 7 constinteger nsys = 99 !THE MAXIMUM NUMBER OF FILE SYSTEMS ON EMAS. !THE TOTAL NUMBER OF SYSTEM INDICES. constinteger total indices = 99 !MAXIMUM NUMBER OF INDICES ON THE SYSTEM. conststring (9) jtxt="Journal: " ownstring (8) control="JJMASTER" !THE IDENTITY OF THE SYSTEM CONTROL FILE. conststring (8) pdstore="JJ#PD" !THE JOURNAL SYSTEM STORAGE FILE. conststring (6) spool="SPOOLR" conststring (6) me = "JOURNL" conststring (8) prime start time="09.30.00" conststring (8) prime end time="17.00.00" !THESE PRIME TIMES DECIDE WHEN RESTRICTED TRIGGERING(TEST C) !OF THE JOURNAL HOUSEKEEPING IS IN FORCE. constinteger yes = 1 constinteger no = 0 conststring (1) snl=" " externalinteger chpointer externalinteger flen externalinteger endflag !THESE LAST THREE INTEGERS ARE CONNECTED WITH THE 'ATOM' !READING FUNCTIONS. !**********EXTERNAL ROUTINE LIST ! THE FOLLOWING EXTERNAL ROUTINES EXIST IN THIS MODULE AND ARE IN ! ALPHABETIC ORDER OF APPEARANCE: ! ABORT JOURNAL FILES: THIS IS USED WHEN THERE HAS BEEN AN ABNORMAL NUMBER ! OF FILES QUEUED FOR JOURNL IN SPOOLR SUCH THAT JOURNAL'S INDEX FILLS ! WHEN IT TRIES TO TAKE THEM OFF SPOOLR. USING THIS COMMAND WE DESTROY ! ALL THE FILES TAKEN FROM SPOOLR WAITING TO BE INDEXED IN THE JOURNAL ! SYSTEM AND HENCE CLEARING THE JOURNL PROCESS DOWN. ! THIS WILL MEAN THAT THE FILES WILL BE LOST FOR GOOD BUT THE FILES WILL ! PROBABLY BE RUBBISH PRODUCED FROM MONITORING IN THE FIRST PLACE ! AND HENCE DISCARDABLE. ! ABORT JOURNAL TAPE: USED WHEN A TAPE HAS BEEN COMPLETELY SCREWED ! AND WE WANT TO USE ANOTHER AND CLEAR DOWN THE INDEX ENTRIES FOR ! THE FILES ON THIS TAPE(SINCE THEY ARE EFFECTIVELY LOST). THIS CAN ! BE USED FOR EITHER THE CURRENT MASTER TAPE OR FOR ANY OTHER TAPE ! THAT MAY BE LOST? ETC. ! CREATE JOURNAL SYSTEM: THIS ROUTINE INITIALISES THE JOURNAL SYSTEM ! AND CAN ONLY BE RUN WHEN THE SYSTEM CONTROL FILE DOES NOT EXIST. ! THE FILE 'JJMASTER' IS CREATED BY THIS ROUTINE ! TOGETHER WITH ALL THE "SYSTEM FILE" INDICES DEFINED IN THE ABOVE ! CONSTARRAY 'SYSTEM KEYWORD'. ! JOURNAL: THIS IS THE MAIN CONTROL ROUTINE OF THE JOURNAL SYSTEM. ! IT IS RUN AT LEAST ONCE EVERY 24 HOURS AND IS RESPONSIBLE FOR THE ! COLLECTING, PARTITIONING, DUMPING TO TAPE OF ALL JOURNAL AND DONOR ! FILES. IT ALSO PRODUCES THE AUTOMATIC ANALYSES SUCH AS THE ERROR ! LOG COMPONENTS. ! IF IT IS OBVIOUS THAT A FILE IS CAUSING REPEATED CRASHES ! THEN THE SYSTEM MANAGER CAN USE THE PARAMETER "KILLFILE" WHICH ! WILL RESULT IN THE FILE LOGGED AS BEING THE LAST FAILING FILE ! IN THE MASTER CONTROL FILE WILL BE REMOVED FROM SPOOLER QUEUE. ! THE SYSTEM CAN BE RUN WITHOUT THE TAPE DUMP BY GIVING THE ! PARAMETER "TAPESKIP" AND WITHOUT AUTO ANALYSIS USING "ANALSKIP" ! JOURNAL STATE:THIS ROUTINE WILL GIVE A SUMMARY OF THE CURRENT STATE ! OF THE JOURNAL SYSTEM INCLUDING DETAILS OF ALL INDICES IN USE, ! DETAILS OF THE TAPE CYCLE AND THE CURRENT MASTER TAPE ETC. ! LIST JOURNAL INDEX: THIS ROUTINE WILL DUMP A FULL LIST OF THE ! CONTENTS OF AN INDEX INTO THE FILE "JLIST". JLIST CAN ! THEN BE LISTED OR VIEWED BY THE USER. ! NEW JOURNAL INDEX: THIS ROUTINE WILL CREATE A NEW INDEX (UNLESS ! IT ALREADY EXISTS) FOR THE KEYWORD SPECIFIED BY THE REPLY ! TO THE GIVEN PROMPT. EACH INDEX IS 90 PAGES LONG AND CAN HOLD A ! MAXIMUM OF 10, 000 ENTRIES. AN ENTRY(BY ROUTINE "CREATE JOURNAL ! SYSTEM" ONLY) WITH PARAMETER "SYSTEM" WILL CREATE ALL THE "SYSTEM" ! INDICES AND IF IT FAILS AT ALL WILL DESTROY ALL THE SYSTEM FILES ! ALREADY CREATED, INCLUDING JJMASTER, FOR A CLEAN RETRY. ! THE FIRST 10 INDICES ARE RESERVED FOR SYSTEM INDICES, THE ! REMAINDER BEING AVAILABLE TO THE INSTALLATION. ! NEW JOURNAL TAPE: THIS IS USED WHEN A NEW TAPE IS TO BE ADDED TO ! THE JOURNAL TAPE CYCLE. THE TAPE WILL BE REJECTED IF IT IS ALREADY ! IN THE CYCLE OTHERWISE AN ACCEPTANCE MESSAGE WILL BE GIVEN ! TOGETHER WITH A COUNT OF THE TAPES IN THE CYCLE. ! REMOVE JOURNAL INDEX: THIS ROUTINE IS USED TO DESTROY AN INDEX AND ! IN DOING SO REMOVING ALL ACCESS TO THE FILES STORED UNDER THAT ! INDEX. ! ************************************************************************ ! ************************************************************************ ! ************************************************************************ externalroutine abort journal files(string (255) s) integer flag destroy(pdstore, flag) if flag#0 start printstring(jtxt."Cannot destroy partition ".pdstore.", flag: ") write(flag, 3); newline finish else start printstring(jtxt."All pending files destroyed") newline finish newpdfile(pdstore) cherish(pdstore) end ; !OF ABORT JOURNAL FILES ! *************************************************************** ! *************************************************************** ! *************************************************************** externalroutine abort journal tape(string (255) s) record (f tape cycle)arrayformat af tape cycle(1:100) record (f index list)arrayformat af index list(0:total indices) record (f index entry)arrayformat af index entry(0:index top) record (rf)r integername master entry, total chapters, total epages, tape count record (f tape cycle)arrayname tape cycle record (f index list)arrayname index list record (f index entry)arrayname index entry integer i, j, k, files lost, flag, new master, max string (15) ss, index string (6) tsn byteinteger id connect(control, 3, 0, 0, r, flag) if flag#0 then master file failure(control, flag) master entry==integer(r_conad+x'708') total epages==integer(r_conad+x'714') total chapters==integer(r_conad+x'710') tape cycle==array(r_conad+x'720', af tape cycle) tape count==integer(r_conad+x'700') index list==array(r_conad+x'30', af index list) cycle prompt("JOURNAL TAPE:") read prompt reply(ss) exit if length(ss)=6 printstring("??"); newline repeat for k=1, 1, tape count cycle exit if tape cycle(k)_tsn=ss if k=tape count start printstring(ss." not a Journal cycle tape!") newline return finish repeat files lost=0; !COUNT OF FILES ON THE BAD TAPE. for i=0, 1, total indices cycle if index list(i)_identity#"" start id=index list(i)_id char index="JJ#".intostr(id)."DEX" connect(index, 3, 0, 0, r, flag) if flag#0 then master file failure(index, flag) index entry==array(r_conad+x'40', af index entry) for j=0, 1, index top cycle if index entry(j)_tape=ss start if 1<=index entry(j)_status<9 then index entry(j)_status=9 c and files lost=files lost+1 finish repeat disconnect(index, flag) finish repeat printstring("There were ".intostr(files lost)." files on the tape.") newline unless k=master entry start printstring("Bad tape marked unused, please replace with") printstring(" a new tape with the same label.") newline tape cycle(k)_age=0 disconnect(control, flag) printstring("Abort succeeds."); newline return finish !OTHERWISE WE KNOW THE TAPE WAS THE MASTER TAPE. new master=-1 for i=1, 1, tape count cycle if tape cycle(i)_age=0 then new master=i and exit repeat if new master=-1 start !WE MUST USE A FULL TAPE(THE OLDEST.) max=10000 for i=1, 1, tape count cycle if tape cycle(i)_age<max and tape cycle(i)_age#-1 start max=tape cycle(i)_age new master=i finish repeat tsn=tape cycle(new master)_tsn printstring("Reusing ".tsn." as replacement master tape") newline for i=0, 1, total indices cycle if index list(i)_identity#"" start id=index list(i)_id char index="JJ#".intostr(id)."DEX" connect(index, 3, 0, 0, r, flag) if flag#0 then master file failure(index, flag) index entry==array(r_conad+x'40', af index entry) for j=0, 1, index top cycle if index entry(j)_tape=tsn start if index entry(j)_status>1 start index entry(j)_status=9 integer(r_conad+x'2C')=j finish finish repeat disconnect(index, flag) finish repeat finish else start printstring("New master tape ".tape cycle(new master)_tsn) newline finish printstring("Bad tape marked unused, please replace with a new tape") newline printstring("with the same label."); newline tape cycle(k)_age=0 tape cycle(new master)_age=-1 master entry=newmaster total chapters=0 total epages=0 disconnect(control, flag) printstring("Abort succeeds."); newline return end ; !OF ABORT JOURNAL TAPE ! ******************************************************************* ! ******************************************************************* ! ******************************************************************* externalroutine abort main analysis(string (255) s) record (rf)r; integer flag connect("JJ#0DEX", 3, 0, 0, r, flag) if flag#0 start printstring(jtxt."Problems..cannot connect Mainlog index, ") printstring("flag:".intostr(flag)) newline return finish integer(r_conad+x'28')=integer(r_conad+x'20') printstring(jtxt."Current analysis aborted.") newline end ! ******************************************************************* ! ******************************************************************* ! ******************************************************************* externalroutine abort volums analysis(string (255) s) record (rf)r; integer flag connect("JJ#1DEX", 3, 0, 0, r, flag) if flag#0 start printstring(jtxt."Problems..cannot connect Volums log index, ") printstring("flag:".intostr(flag)) newline return finish integer(r_conad+x'28')=integer(r_conad+x'20') printstring(jtxt."Current analysis aborted.") newline end ! ******************************************************************* ! ******************************************************************* ! ******************************************************************* externalroutine abort spoolr analysis(string (255) s) record (rf)r; integer flag connect("JJ#2DEX", 3, 0, 0, r, flag) if flag#0 start printstring(jtxt."Problems..cannot connect Spoolr log index, ") printstring("flag:".intostr(flag)) newline return finish integer(r_conad+x'28')=integer(r_conad+x'20') printstring(jtxt."Current analysis aborted.") newline end ! ******************************************************************* ! ******************************************************************* ! ******************************************************************* externalroutine abort direct analysis(string (255) s) record (rf)r; integer flag connect("JJ#4DEX", 3, 0, 0, r, flag) if flag#0 start printstring(jtxt."Problems..cannot connect Direct log index, ") printstring("flag:".intostr(flag)) newline return finish integer(r_conad+x'28')=integer(r_conad+x'20') printstring(jtxt."Current analysis aborted.") newline end ! ************************************************************************ ! ************************************************************************ ! ************************************************************************ externalroutine create journal system(string (255) s) record (f index list)arrayformat af index list(0:total indices) record (f tape cycle)arrayformat af tape cycle(1:100) record (f index list)arrayname index list record (f tape cycle)arrayname tape cycle string (7) arrayformat af pending files(1:250) stringarrayname pending files record (rf)r integer i, flag, conad connect(control, 0, 0, 0, r, flag) if flag=0 start printstring(jtxt.control." already exists??") newlines(2) return finish !WE NOW KNOW THAT JJMASTER DOES NOT EXIST AND THAT THE SYSTEM HAS !NOT ALREADY BEEN SET UP. PROCEED WITH SET UP. outfile(control, 3*4096, 0, 0, conad, flag) if flag#0 start printstring(jtxt."Failed to create JJMASTER, flag ") write(flag, 2) newlines(2) return finish !NOW SET THE INITIAL VALUES TO JJMASTER. integer(conad) = integer(conad+8); ! Set data length = physical length integer(conad+x'20') = current packed dt integer(conad+x'24')=0; !THE JOURNAL STATE SETTING. integer(conad+x'28')=0; !THE ICL ERROR ENTRY CYCLIC COUNT(LAST TWO BYTES) integer(conad+x'6D8')=0; !THE FAILURE DESCRIPTOR. integer(conad+x'6DC')=0; !AUTO CONTROL FLAG index list==array(conad+x'30', af index list) !NOW INITIALISE THE INDEX DESCRIPTORS. for i=0, 1, total indices cycle index list(i)_id char=i index list(i)_data type=0 !IE 0: TEXT(TEXT DATA). 1: MAPPED DATA. index list(i)_identity="" repeat !NOW CREATE THE TAPE CYCLE CONTROL. string(conad+x'6F2')=""; !IDENTIFIES LAST FAILING FILE. integer(conad+x'700')=0; !TAPES IN CYCLE integer(conad+x'704')=1; !AGE OF NEXT TAPE integer(conad+x'708')=-1; !INITIAL MASTER TAPE ENTRY integer(conad+x'70C')=7000; !Max epages per dump tape. integer(conad+x'710')=0; !TOTAL CHAPTERS ON MASTER TAPE. integer(conad+x'714')=0; !TOTAL EPAGES ON MASTER TAPE. tape cycle==array(conad+x'720', af tape cycle) for i=1, 1, 100 cycle tape cycle(i)_tsn="" tape cycle(i)_age=-2 repeat integer(conad+x'1FFC')=0; !COUNT OF THE FILES IN THE PENDING FILES ARRAY. pending files==array(conad+x'2000', af pending files) !THIS ARRAY POINTS TO THE FILES IN JOURNL TAKEN FROM SPOOLER TO BE PROCESSED. string(conad+x'6EA')=""; !THIS IS THE BAD FILE POINTER. string(conad+x'27D0') = ""; ! Null background password. journal backpass("") byteinteger(conad+x'27DC') = 0; ! Count for next autojob logfile. disconnect(control, flag) printstring(jtxt."JJMASTER initialised.") newlines(2) cherish(control) !NOW SET UP THE SYSTEM INDICES. new journal index("SYSTEM") printstring("The Journal system requires at least two tapes") newline printstring("for operation. Add these two tapes through the ") newline printstring("following prompts. Any further tapes can be added using") newline printstring("the command 'NEW JOURNAL TAPE'.") newline new journal tape(s) new journal tape(s) printstring("The Journal system is now initialised."); newline printstring("The first run of the housekeeping command: JOURNAL") printstring(" will initiate (on its"); newline printstring("successful completion) the automatic housekeeping.") newline return end ; !OF CREATE JOURNAL SYSTEM. ! ******************************************************************** ! ******************************************************************** ! ******************************************************************** ! ROUTINES THAT GIVE DIRECT CALLED ACCESS TO THE HOUSEKEEPING. externalroutine journal override(string (255) s) journal("OVERRIDE") end externalroutine journal recovery(string (255) s) journal("") end externalroutine update journal(string (255) s) journal("TAPESKIP,ANALSKIP,EXTERNAL") end ! ************************************************************************ ! ************************************************************************ ! ************************************************************************ externalroutine journal(string (255) s) owninteger run tape ! Stops tape dump run if no files owninteger tapeskip owninteger analskip owninteger auto call owninteger decks owninteger killfile owninteger closetape owninteger external; !USED WHEN 'JOURNAL' CALLED BY 'FULL JOURNAL ANALYSIS'. owninteger call state; !ALSO USED IN ABOVE CASE. owninteger write unit=1 !THE TAPE CONTROL UNIT IDENTITIES. owninteger abandon tape retries = 2 !IE LEVEL OF RETRY THAT WILL RESULT IN AUTO JOURNAL JOBS BEING !STOPPED IF UNSUCCESSFUL. owninteger on = 1 owninteger off = 0 owninteger tape retry level= -1 !THE RETRY COUNTER. owninteger override !THE OVERRIDE FLAG. recordformat f finf(integer nkb, rup, eep, apf, use, arch, fsys, conseg, cct, codes, codes2, ssbyte, string (6) offer) record (f finf)finf recordformat f req(integer dest, srce, flag, string (6) user, file, integer p6) recordformat f rep a(integer dest, srce, flag, string (6) file, string (11) output q) recordformat f rep b(integer dest, srce, byteinteger flag, string (6) file, string (15) output q) recordformat f file list(integer files, integerarray dts(1:100), string (7) array names(1:100)) record (f file list)array file list(0:total indices) record (f file list)name fli record (f index entry)arrayformat af index entry(0:index top) record (f index list)arrayformat af index list(0:total indices) record (f tape cycle)arrayformat af tape cycle(1:100) record (f index entry)arrayname index entry record (f index list)arrayname index list record (f tape cycle)arrayname tape cycle record (f chapter header)name chapter header record (f parameters)name parameters record (f req)req record (f rep a)name repa record (frep b)name repb record (f repb)poff rep record (rf)r record (f parm)p record (f queue)name queue string (7) arrayformat af pending files(1:250) stringarrayname pending files string (11) backpass byteintegername nextjjlog externalintegerfnspec dpon2(string (6) user, record (f req)name p, integer msgtype, outno) externalintegerfnspec dfinfo(string (6) user, string (11) file, integer fsys, addr) recordformat f parm(integer dest, srce, p1, p2, p3, p4, p5, p6) externalintegerfnspec dpon3(string (6) user, record (f parm)name p, integer invoc, msgtype, outno) routinespec remove failing file routinespec bulk change index status(string (12) keyword, byteinteger old status, new status) routinespec collect journal files routinespec connect control file routinespec connect index(string (15) index, integer mode, integername addr) routinespec date and time(integer index slot) routinespec dump to tape routinespec check file(string (*)name file, byteintegername c data type, integername flag) routinespec file list from spooler integerfnspec autojob(string (15) name, string (*)name ident) routinespec respool journal(string (15) name) routinespec remove queued file(string (6) file) routinespec requeue file(string (6) file) routinespec start up byteintegerarrayformat af buff(1:10000000) byteintegerarrayname buff switch journal state(0:5) integername relative age, master entry, p file count integername system state, run date, total chapters, tape count integername autoflag, fail type, total epages, max epages string (*)name fail file, bad file string (140) array atoms(1:68) string (16) index, new file name, start date, start time, identj string (16) finish date, finish time, poff file; poff file="" string (64) s1, ss integer i, flag, index addr, free slot, sequence number, entry integer queues, prime start, prime end prime start=packdateandtime(date, prime start time) prime end=packdateandtime(date, prime end time) string (255) pstring byteinteger id char, datatype !THE MAIN CONTROL CODE BEGINS HERE. connect control file !CONNECT THE CONTROL FILE. respool journal("MONITOR") if autojob("MONITOR", identj)=no disconnect("JJINF", flag); destroy("JJINF", flag) destroy("JLIST", flag) destroy("JJANL", flag) destroy("JWORKFILE", flag) !THIS IS A GENERAL WORK FILE THAT EXISTS ONLY FOR RUNS OF CERTAIN ANALYSES. !DESTROY IT IF IT IS FOUND HANGING AROUND!! if s#"" start !THE CALL HAD A PARAMETER LIST. !POSSIBLE PARAMETER COMBINATIONS:- ! !'OVERRIDE, EXTERNAL': !CALL FROM ENGINEERS(PACKAGE C) TO UPDATE !JEF. REQUIRES A FULL COLLECTION, NO TAPE DUMP AND AN AUTO MAINLOG !ANALYSIS. IT IS LEFT IN THE 'TAPE DUMP SKIPPED' STATE !WHICH WILL TRIGGER THE NEXT AUTO HOUSEKEEPING TO TIDY UP. ! !'TAPESKIP, ANALSKIP, EXTERNAL': !A CALL FROM THE COMMAND 'UPDATE JOURNAL' TO UPDATE THE !JOURNAL SYSTEM WITH THE FILES QUEUED BY SPOOLR.. LEFT IN STATE !AS ABOVE. ! !'AUTOCALL': !THIS IS THE ENTRY MADE BY THE AUTOMATIC HOUSEKEEPING HOURLY BATCH JOB. !IF IT DECIDES THAT A FULL RUN IS REQUIRED IT WILL DETACH !A SECOND BATCH JOB TO RUN AS SOON AS POSSIBLE WITH ENTRY AS BELOW. ! !'AUTOCALL+DECK': !THIS ENTRY IS MADE BY THE ABOVE ENTRY BEING CALLED EARLIER AND !DECIDING THAT A FULL RUN IS REQUIRED. THIS JOB ENTRY WILL !REQUEST AN MTU FOR THE RUN. ! !'OVERRIDE': !THIS IS THE CALL TO OVERRIDE THE LOCK IMPOSED ON RUNNING THE !HOUSEKEEPING WHEN THE AUTOMATIC HOUSEKEEPING IS IN AN UNFAILED STATE !OR THE OPERATORS MAY RUN THIS TO INSTITUE A RECOVERY FROM ANY !SUSPECTED ERRORS. ! printstring("Parameter list: ".s) newlines(2) flag=0 for i=1, 1, 4 cycle if s->s1.(",").s start if s1="TAPESKIP" then tapeskip=1 if s1="ANALSKIP" then analskip=1 if s1="KILLFILE" then killfile=1 if s1="EXTERNAL" then external=1 if tapeskip+analskip+killfile+external#i then flag=1 and exit finish else exit repeat if s="TAPESKIP" then tapeskip=1 if s="ANALSKIP" then analskip=1 if s="KILLFILE" then killfile=1 if s="EXTERNAL" then external=1 if s="AUTOCALL" then autocall=1 if s="AUTOCALL+DECK" then decks = on and autocall=on if s="OVERRIDE" then override=1 if s="CLOSETAPE" then closetape=1 if tapeskip+analskip+killfile+external+autocall+override+closetape#i c then flag=1 if (autocall=on) and i#1 then flag=1 if override=on start if external#on start if i#1 then flag=1 finish finish if flag=1 start printstring(jtxt."Parameter list faulty!".snl) return finish if killfile=1 then remove failing file if closetape=1 then max epages = 0 ! Reset (to 7000) by next call of START NEWTAPE. finish connect(spool.".CFILE", 9, 0, 0, r, flag) if flag#0 start !WE CANNOT CONNECT THE SPOOLR INFO FILE. printstring("Spoolr descriptor file (CFILE) connect fails:") write(flag, 3) and newline printstring("Log off and try again.".snl) stop finish queues=integer(r_conad+x'18') if queues=0 start printstring("No queues defined in SPOOLR descriptor file".snl) stop finish for i=1, 1, queues cycle queue==record(r_conad+x'20'+148*(i-1)) if queue_name="JOURNAL" then exit if i=queues start printstring("Journal queue not in SPOOLR descriptor file".snl) stop finish repeat if autoflag=on and autocall=off and override=off start !IE A MANUAL RUN OF JOURNAL IS NOT ALLOWED WHEN THE AUTO !JOURNAL SYSTEM IS IN AN UNFAILED STATE. unless external=on start printstring(jtxt."Manual run not permitted whilst auto".snl) printstring(" Journal is in unfailed state.".snl) stop finish !ALTHOUGH ALLOW CALL FROM UPDATE JOURNAL. finish if override=on and external=off start !We have a manual run interrupting the auto run sequence. autoflag=off fail type=0 finish if override=on and external=on start !IE A CALL FROM THE ENGINEERS COMMAND 'UPDATE JEF'. if autoflag=off or (system state#0 and system state#2) c start printstring("Journal system in failed state, please log") printstring(" off and inform ops."); newline return finish autoflag=off; tapeskip=on printstring("Updating JEF") newline finish start up; !FIND OUT HOW TO START UP THIS RUN OF JOURNAL HOUSEKEEPING !NOW CLOSE THE CURRENT MAINLOG. p=0 p_dest=x'FFFF0000'!27 i=dpon3("DIRECT", p, 0, 1, 7) -> journal state(system state) journal state(0): !IF THE SET TESTS ARE POSITIVE (IE THE PD IS FILLING UP) THEN !DESTROY THE PARTITION AMENDING THE STATUS SETTINGS IN THE !INDICES FROM "ON PD AND TAPE" TO "ON TAPE ONLY". THEN CREATE !A NEW 24 HOUR PARTITION. i=dfinfo(me, "JJ#PD", -1, addr(finf)) if i#0 start printstring("Journal DFINFO fails, max assumed".snl) finf_nkb=3001 finish if (finf_nkb>1000 and (finf_nkb*1024+queue_amount)>1024*3500) c or (finf_nkb*1024+queue_amount)>1024*4000 start bulk change index status("ALL", 1, 2) !ALL STATUS AMENDMENTS MADE. destroy(pdstore, flag) newpdfile(pdstore) cherish(pdstore) finish journal state(2): journal state(3): !RESTART WITH EXISTING PD FILE OR DROP THROUGH FROM ABOVE. !STATE 3 CAN ONLY BE REACHED BY EXTERNAL CALL FROM 'UPDATE !JOURNAL' WHEN A TAPE DUMP HAS PREVIOUSLY FAILED AND !WE WISH TO ALLOW A FILE COLLECTION TO TAKE PLACE WHILST !RETAINING THE TAPE DUMP FAILURE CONTINGENCY( THE CALL WILL !BE ACCOMPANIED BY 'TAPESKIP' AND 'ANALSKIP') if system state=3 then call state=3 !IE REMOTE CALL OF JOURNAL AFTER A PREVIOUS TAPE CONTINGENCY. system state=1 !SETTING THE SYSTEM STATUS TO DEFAULT COLLECTION FAILURE. collect journal files journal state(4): !FORCED DUMP TO TAPE OR FALL THROUGH FROM ABOVE. if tape skip=0 start cycle system state = 3; ! Default state during tape dump. dump to tape exit if system state=0; ! Tape dump successful. tape retry level=tape retry level+1 if tape retry level=abandon tape retries start printstring("Multiple tape failure, auto Journal runs suspended.".snl) printstring("See Journal documentation, failure no: 1.".snl) auto flag=off ss=" JOURNAL SYSTEM FAILS FAILURE NO: 1." byteinteger(addr(ss)+1)=17 !MAKE THE OPER MESSAGE FLASH. fail type=1 oper(0, ss) return !I.e. we have failed in the tape dump consistently, so stop auto runs ! and inform the operators of failure. The System management will ! then have to sort out the tape problem (fail type 1). finish printstring(jtxt."Dump to tape failed, retry level:") printstring(intostr(tape retry level).snl) oper(0, "JOURNAL:TRY A NEW DECK") repeat finishelsestart if call state=3 then system state=3 else system state=2 ! I.e. if remote call from 'UPDATE JOURNAL' then any tape !contingency is retained through the call, else assign 'SKIP' state. printstring(jtxt."Tape dump omitted as requested.".snl) finish if analskip=1 start printstring(jtxt."Ended without auto analyses as requested".snl) if autoflag=off then autoflag=on !WE CAN ALLOW AUTO SYSTEM TO RUN SINCE COLLECTION IS OK. disconnect(control, flag) return finish autoflag=off; fail type=4 !SET THE FAIL TYPE FOR AUTO ANALYSIS FAILURE. !NOW PERFORM THE MAIN LOG ANALYSIS FOR ''TODAY'' parameters==record(addr(pstring)+1) parameters_keyword="MAINLOG" parameters_analysis="AUTOMATIC" index="MAINLOG" identify index(index, id char, data type, entry) index="JJ#".intostr(id char)."DEX" connect index(index, 3, index addr) parameters_lower file<-intostr(integer(index addr+x'28')) if integer(index addr+x'28')=integer(index addr+x'20') start printstring(jtxt."No files for automatic analysis (MAINLOG)".snl) finish else start parameters_upper file<-intostr(cyclic(integer(index addr+x'20'), -1)) byteinteger(addr(pstring))=x'30' printstring(jtxt."Running automatic analysis (MAINLOG)".snl) journal analysis(pstring) !THE ANALYSIS HAS NOW BEEN DEFINED AND RUN. !NOW RESET THE RUNNING PARAMETERS IN THE INDEX. integer(index addr+x'28')=integer(index addr+x'20') finish disconnect(index, flag) !AUTO MAINLOG ANALYSIS NOW COMPLETED AND POINTERS RESET. if override=on and external=on start printstring("JEF updated.") autoflag=on; failtype=0 return finish !NOW PERFORM THE SPOOLR ANALYSIS FOR ''TODAY'' fail type=5; !SET FAIL TYPE FOR SPOOLR ANALYSIS. parameters==record(addr(pstring)+1) parameters_keyword="SPOOLR" parameters_analysis="AUTOMATIC" index="SPOOLR" identify index(index, id char, data type, entry) index="JJ#".intostr(id char)."DEX" connect index(index, 3, index addr) parameters_lower file<-intostr(integer(index addr+x'28')) if integer(index addr+x'28')=integer(index addr+x'20') start printstring(jtxt."No files for automatic analysis (SPOOLR)".snl) finish else start parameters_upper file<-intostr(cyclic(integer(index addr+x'20'), -1)) byteinteger(addr(pstring))=x'30' printstring(jtxt."Running automatic analysis (SPOOLR)".snl) journal analysis(pstring) !THE ANALYSIS HAS NOW BEEN DEFINED AND RUN. !NOW RESET THE RUNNING PARAMETERS IN THE INDEX. integer(index addr+x'28')=integer(index addr+x'20') finish disconnect(index, flag) !AUTO SPOOLR ANALYSIS NOW COMPLETED AND POINTERS RESET. !NOW PERFORM THE VOLUMS ANALYSIS FOR 'TODAY' fail type=6; !SET FAIL TYPE FOR VOLUMS ANALYSIS. parameters==record(addr(pstring)+1) parameters_keyword="VOLUMS" parameters_analysis="AUTOMATIC" index="VOLUMS" identify index(index, id char, data type, entry) index="JJ#".intostr(id char)."DEX" connect index(index, 3, index addr) parameters_lower file<-intostr(integer(index addr+x'28')) if integer(index addr+x'28')=integer(index addr+x'20') start printstring(jtxt."No files for automatic analysis (VOLUMS)".snl) finish else start parameters_upper file<-intostr(cyclic(integer(index addr+x'20'), -1)) byteinteger(addr(pstring))=x'30' printstring(jtxt."Running automatic analysis (VOLUMS)".snl) journal analysis(pstring) !THE ANALYSIS HAS NOW BEEN DEFINED AND RUN. !NOW RESET THE RUNNING PARAMETERS IN THE INDEX. integer(index addr+x'28')=integer(index addr+x'20') finish disconnect(index, flag) !AUTO VOLUMS ANALYSIS NOW COMPLETED AND POINTERS RESET. !NOW PERFORM THE DIRECT ANALYSIS FOR 'TODAY' fail type=7; !SET FAIL TYPE FOR DIRECT ANALYSIS. parameters==record(addr(pstring)+1) parameters_keyword="DIRECT" parameters_analysis="AUTOMATIC" index="DIRECT" identify index(index, id char, data type, entry) index="JJ#".intostr(id char)."DEX" connect index(index, 3, index addr) parameters_lower file<-intostr(integer(index addr+x'28')) if integer(index addr+x'28')=integer(index addr+x'20') start printstring(jtxt."No files for automatic analysis (DIRECT)".snl) finish else start parameters_upper file<-intostr(cyclic(integer(index addr+x'20'), -1)) byteinteger(addr(pstring))=x'30' printstring(jtxt."Running automatic analysis (DIRECT)".snl) journal analysis(pstring) !THE ANALYSIS HAS NOW BEEN DEFINED AND RUN. !NOW RESET THE RUNNING PARAMETERS IN THE INDEX. integer(index addr+x'28')=integer(index addr+x'20') finish disconnect(index, flag) !Auto Direct analysis now completed and pointers reset. printstring(jtxt."Requested run of Journal completed.".snl) fail type=0; autoflag=on disconnect(control, flag) return routine remove failing file !HERE WE REMOVE THE QUEUED FILE THAT IS CAUSING REPEATED FAILURES integer i string (16) s, ns1 if fail file="" start printstring(jtxt."No record of a failing file!".snl) stop finish if fail file->ns1.(spool.".").s and ns1="" start printstring(jtxt."Marking ".fail file." for deletion.".snl) bad file=s disconnect(control, flag) stop finish else start for i=1, 1, p file count cycle if pending files(i)=fail file then pending files(i)="" repeat destroy(fail file, flag) printstring(jtxt."File ".fail file." destroyed.".snl) fail file="" disconnect(control, flag) stop finish end ; !OF REMOVE FAILING FILE. routine bulk change index status(string (12) keyword, byteinteger old, new) !THIS ROUTINE WILL CONNECT THE DEFINED INDEX (ALL INDICES IF KEYWORD != "ALL" ) AND WILL CHANGE ALL STATUS VALUES THAT ARE AT PRESENT "OLD" !TO "NEW" !JJMASTER MUST BE CONNECTED AND INDEX LIST MAPPED ON ENTRY TO THIS !ROUTINE. byteinteger status integer i, k, top file for i=0, 1, total indices cycle !LOOK UP THE LIST OF INDICES. if (keyword="ALL" or keyword=index list(i)_identity) and c index list(i)_identity#"" start index="JJ#".intostr(index list(i)_id char)."DEX" connect index(index, 3, index addr) top file=integer(index addr+x'20'); !THE TOP FILE(+1)OF THE INDEX if integer(index addr+x'24')#0 start !THERE ARE FILES ON THE INDEX. k = top file cycle k = cyclic(k,-1) ! Backwards to save cpu. status=index entry(k)_status exit if status=2 or status=8 !IE IF FILES ON TAPE ARE FOUND OR ENTRY UNUSED, THEN WE HAVE ! Gone far enough back through the index. if status=old then index entry(k)_status=new repeat until k=top file finish disconnect(index, flag) finish repeat end ; !OF BULK CHANGE INDEX STATUS. routine collect journal files !THIS ROUTINE TAKES ALL THE FILES OFF THE INPUT QUEUE AND PUTS THEM !ON THE 24 HOUR PARTITION AT THE SAME TIME MAKING AN ENTRY FOR EACH !FILE IN THE RELEVANT INDEX. THE CONTROL OF THE SYSTEM IS MAINTAINED !BY UPDATING THE CONTROL AREAS OF THE CONTROL FILE AND INDICES. integer flag, i, ind, fls byteinteger data type !DATA TYPE: DEFINES THE FILE INFORMATION TYPE IE TEXT(TEXT DATA) OR MAPPED DATA. string (31) file, seq file list from spooler for ind=0, 1, total indices cycle fli == file list(ind) continue unless fli_files>0 data type=index list(ind)_data type ! There are files to be taken of this type. !ID CHAR IS DEFINED BY IND. index="JJ#".intostr(ind)."DEX" connect index(index, 3, index addr) for fls=1, 1, fli_files cycle file=fli_names(fls) check file(file, data type, flag) continue unless flag=0 free slot=integer(index addr+x'20') sequence number=integer(index addr+x'24') seq=intostr(sequence number); !THE STRING VERSION OF THE SEQUENCE !WE NOW HAVE THE INDEX POSITION AND NEW IDENTITY NUMBER OF !THE NEW FILE. new file name="J".intostr(ind)."I".seq !THE NEW FILE NAME. index entry(free slot)_file id = sequence number rename(pdstore."_".file.",".pdstore."_".newfilename) connect(pdstore."_".newfilename, 0, 0, 0, r, flag) monitor and stop if flag#0; !SHOULD NOT HAPPEN. date and time(free slot) index entry(freeslot)_status=0 integer(index addr+x'20') = cyclic(freeslot, 1) integer(index addr+x'24') = cyclic(sequence number, 1) for i=1, 1, p file count cycle if pending files(i)=file then pending files(i)="" c and exit repeat run tape=1 repeat disconnect(index, flag) repeat p file count=0 !IE THERE ARE NO FILES ON THE PENDING FILE LIST NOW(ALL !ENTRIES SHOULD BE "") printstring(jtxt."File collection completed.".snl) end ; !OF COLLECT JOURNAL FILES. routine connect control file !THIS ROUTINE WILL CONNECT THE MASTER CONTROL FILE JJMASTER AND !ALL THE NAMES LINKED TO IT . integer flag connect(control, 3, 0, 0, r, flag) if flag#0 then master file failure(control, flag) system state==integer(r_conad+x'24') run date==integer(r_conad+x'20') master entry==integer(r_conad+x'708') !THE POINTER FOR THE ENTRY TO THE CURRENT MASTER TAPE. max epages==integer(r_conad+x'70C') total epages==integer(r_conad+x'714') total chapters==integer(r_conad+x'710') tape cycle==array(r_conad+x'720', af tape cycle) tape count==integer(r_conad+x'700') relative age==integer(r_conad+x'704') fail type==integer(r_conad+x'6D8') autoflag==integer(r_conad+x'6DC') !THE AUTO RUN PERMISSION FLAG. fail file==string(r_conad+x'6F2') index list==array(r_conad+x'30', af index list) p file count==integer(r_conad+x'1FFC') pending files==array(r_conad+x'2000', af pending files) bad file==string(r_conad+x'6EA') back pass <- string(r_conad+x'27D0') nextjjlog == byteinteger(r_conad+x'27DC') end ; !OF CONNECT CONTROL FILE. routine connect index(string (15) index, integer mode, integername addr) !THIS ROUTINE WILL CONNECT THE REQUIRED INDEX IN THE MODE !DEFINED AND WILL MAP THE "INDEX ENTRY" ARRAY ONTO IT. THE !CONNECT ADDRESS IS PASSED BACK IN ADDR. integer flag connect(index, mode, 0, 0, r, flag) if flag#0 then master file failure(index, flag) addr=r_conad index entry==array(r_conad+x'40', af index entry) end ; !OF CONNECT INDEX. routine date and time(integer index slot) !THIS ROUTINE IS USED TO ENTER THE RELEVANT DATES AND TIMES !FOR THE FILE IN THE INDEX CONNECTED. THIS WILL BE THE !MEANS OF SEARCH IDENTITY FOR ANY RETRIEVAL FROM THE SYSTEM. if start date#"*" start if start date="" start !IE NO DATES FOUND. if index entry(cyclic(index slot, -1))_status#8 start !IE NOT THE FIRST INDEX ENTRY. index entry(index slot)_starting c =index entry(cyclic(index slot, -1))_finishing index entry(index slot)_finish ing c =index entry(index slot)_starting finish ! Leave index creation date in. This should not happen often. finishelsestart index entry(index slot)_starting c =packdateandtime(start date, start time) index entry(index slot)_finishing c = packdateandtime(finish date, finish time) finish finish else start !IN THIS CASE !MAINTAIN A CONTINUOUS DATE INDEX WE USE THIS AS THE FINISHING !DATE FOR THE FILE AND THE STARTING DATE AS THE FINISHING DATE !OF THE LAST FILE ON THE INDEX. index entry(index slot)_finishing= c pack date and time(finish date, finish time) if index entry(cyclic(index slot, -1))_status#8 start !IE THIS IS NOT THE FIRST ENTRY IN THE INDEX index entry(index slot)_starting= c index entry(cyclic(index slot, -1))_finishing finish else index entry(index slot)_starting= c index entry(index slot)_finishing finish end ; !OF DATE AND TIME. routine dump to tape !THIS ROUTINE WILL DUMP ALL THE INDEXED FILES FROM THE PD FILE !TO MAGNETIC TAPE CONTROLLED BY THE TAPE CYCLE INFORMATION IN !THE CONTROL FILE JJMASTER. integer epages, chapters, file epages, displ, wkaddr integer i, j, k, curraddr, len, file length, existing chapters integer last bytes, count integer tape change; tape change=0 byteintegerarray buffer(0:4095) !THE TAPE IO BUFFER string (6) write tape, full tape string (31) file name connect control file routine tape error(string (64) s) !THIS ROUTINE DEALS WITH MOST OF THE 'EVERYDAY' TYPE OF TAPE ERRORS !OCCURING DURING THE RUN OF THE TAPE DUMP. printstring(jtxt."Tape error detected.".snl) printstring(s.snl) return end ; !OF TAPE ERROR. routine read verify(integername flag) !THIS ROUTINE READS THROUGH THE THE LAST WRITE TAPE !TO ENSURE THAT THERE ARE NO PROBLEMS integer pages, j printstring(jtxt."Verifying ".write tape.snl) len=block skip tm mag(write unit, 1); !GET BEYOND THE LABEL. if chapters>0 start printstring(jtxt."Verify: skipping ".intostr(chapters-1)) printstring(" chapters.".snl) flag=0 f skip tm mag(write unit, chapters-1, flag) if chapters>1 !SKIP TO LAST CHAPTER if flag#0 start printstring(jtxt."Verify: skip fails flag: ".intostr(flag).snl) flag=1 return finish len=block read mag(write unit, wkaddr, len, flag) if flag=1 start printstring(jtxt."Verify: tape mark where header should be!!".snl) flag=1; return finish if flag>1 start printstring(jtxt."Verify: failure on header read , flag: ") write(flag, 3); printstring("Chapter: ") write(chapters, 4) and newline flag=1; return finish if chapter header_type#"JOURNAL" or c chapter header_tape name#write tape or c chapter header_chapter#chapters start printstring(jtxt."Verify: chapter header failure: ".snl) printstring(" should be: ") printstring("Journal ".write tape." ") write(chapters, 4) and newline printstring(" actual: ") printstring(chapter header_type." ".chapter header_tapename) write(chapter header_chapter, 5) and newline flag=1; return finish pages=chapter header_epages for j=1, 1, pages cycle len=block read mag(write unit, wkaddr, len, flag) if flag=1 start printstring(jtxt."Verify: tape mark in middle of file.".snl) printstring(" chapter: ") write(chapters, 4) and newline flag=1; return finish if flag>1 start printstring(jtxt."Verify: failure reading tape, flag: ") write(flag, 3) and newline printstring(" chapter: "); write(chapters, 4) and newline flag=1; return finish repeat read mag(write unit, wkaddr, len, flag) if flag#1 start printstring(jtxt."Verify: no tape mark, chapter: ") write(chapters, 4) and newline flag=1; return finish finish printstring(jtxt."Verify: last existing chapter verified.".snl) flag=0 return end routine verify new chapters(integer existing chapters, chapters, integername flag) !THIS ROUTINE JUST READ VERIFIES THE NEW CHAPTERS ON THE MASTER TAPE. integer pages, i, j, ch count ch count=0 printstring(jtxt."Verifying ".write tape.snl) if chapters-existing chapters>0 start f skip tm mag(write unit, -(chapters-existing chapters+2), flag) if flag#0 start printstring(jtxt."Verify: skip fails flag: ".intostr(flag).snl) return finish !NOW SHOULD BE BEFORE TM OF LAST OLD CHAPTER. skip tm mag(write unit, 1) ch count=0 !NOW AT THE HEADER OF THE FIRST NEW CHAPTER(I HOPE) for i=existing chapters+1, 1, chapters cycle len=block read mag(write unit, wkaddr, len, flag) if flag=1 start printstring(jtxt."Verify: tape mark where header should be!!".snl) flag=1; return finish if flag>1 start printstring(jtxt."Verify: failure on header read , flag: ") write(flag, 3); printstring("Chapter: ") write(i, 4) and newline flag=1; return finish if chapter header_type#"JOURNAL" or c chapter header_tape name#write tape or c chapter header_chapter#i start printstring(jtxt."Verify: chapter header failure: ".snl) printstring(" should be: ") printstring("Journal ".write tape." ") write(i, 4) and newline printstring(" actual: ") printstring(chapter header_type." ".chapter header_tapename) write(chapter header_chapter, 5) and newline if i-chapter header_chapter=1 and c i=existing chapters+1 start !WE HAVE THE SITUATION WHERE THE TAPE MARK OF THE FINAL EXISTING !CHAPTER HAS BEEN OVERWRITTEN BY THE NEW CHAPTERS, WE MUST !RESTORE THE DOUBLE TM AT THE END OF THIS CHPTER BEFORE FAILING. printstring(jtxt."Verify: special last chapter recovery ") printstring("proceeding".snl) pages=chapter header_epages for j=1, 1, pages cycle len=block read mag(write unit, wkaddr, len, flag) if flag=1 then c printstring(" Fails with TM.".snl) and return if flag>1 start printstring(" Fails, flag: ") write(flag, 1) and newline flag=1 return finish repeat !OK WE ARE AT THE END OF THE LAST EXISTING CHAPTER, WRITE TWO TMS. write tmmag(write unit, flag) write tmmag(write unit, flag) printstring(" Recovery OK.".snl) finish flag=1; return finish pages=chapter header_epages ch count=ch count+1 for j=1, 1, pages cycle len=block read mag(write unit, wkaddr, len, flag) if flag=1 start printstring(jtxt."Verify: tape mark in middle of file.".snl) printstring(" chapter: ") write(i, 4) and newline flag=1; return finish if flag>1 start printstring(jtxt."Verify: failure reading tape, flag: ") write(flag, 3) and newline printstring(" chapter: "); write(i, 4) and newline flag=1; return finish repeat read mag(write unit, wkaddr, len, flag) if flag#1 start printstring(jtxt."Verify: no tape mark, chapter: ") write(i, 4) and newline flag=1; return finish repeat finish printstring(jtxt.intostr(chcount)." new chapters verified.".snl) flag=0 return end routine start new tape(integername flag) !THIS ROUTINE IS CALLED WHEN THE CURRENT MASTER TAPE !IS FULL AND NEEDS TO BE REPLACED WITH A FRESH TAPE FROM THE CYCLE. integer i, max record (rf) r max epages = 7000; ! Could have been set to 0 (by JOURNAL(CLOSETAPE) ). printstring(jtxt."Tape dump: ".write tape." full, starting new tape".snl) write tmmag(write unit, flag) if flag#0 start printstring(jtxt."Tape dump: failed to write tape mark.".snl) flag=1; return finish verify new chapters(existing chapters, chapters, flag) if flag=1 then return !IE VERIFY FAILED. unload mag(write unit) full tape=write tape write tape="" for i=1, 1, tape count cycle if tape cycle(i)_age=0 then c write tape=tape cycle(i)_tsn and exit repeat if write tape="" start connect("JENGPD_JENGHD",0,0,0,r,flag) if flag=0 and integer(r_conad+x'100')=5 start ! 2972 - temp frig. oper(0,"LOG INTO JOURNL AND CALL") oper(0,"COMMAND 'NEW JOURNAL TAPE'") stop finish !WE WILL HAVE TO REUSE THE OLDEST TAPE max=10000 for i=1, 1, tape count cycle if tape cycle(i)_age<max and tape cycle(i)_age#-1 start max=tape cycle(i)_age write tape=tape cycle(i)_tsn finish repeat printstring(" reusing ".write tape.snl) finish epages=0 chapters=0 existing chapters=0 !ZEROISE THE CHAPTER COUNT. printstring(jtxt."Tape dump: new write tape: ".write tape.snl) open mag(write unit, write tape."*") skip mag(write unit, 1); !GET BEYOND THE LABEL. write tm mag(write unit, flag) flag=0 len=block return end ; !OF START NEW TAPE. if run tape=0 start printstring(jtxt."No files to dump to tape.".snl) system state=0 return finish wkaddr=addr(buffer(0)) for i=0, 1, block-1 cycle buffer(i)=0 repeat !IE CLEAR DOWN THE IO BUFFER if tape count<2 start printstring(jtxt."Tape dump: only "); write(tape count, 1) printstring(" tapes in the cycle, there must be at least 2.".snl) return finish !WE KNOW THAT THERE ARE SUFFICIENT TAPES IN THE CYCLE. if master entry=-1 start !THIS MUST BE THE FIRST RUN OF THE SYSTEM! master entry=1 tape cycle(1)_age=-1 finish write tape=tape cycle(master entry)_tsn chapter header==record(wkaddr) !MAP THE CHAPTER HEADER RECORD ONTO THE I/O AREA. chapters = total chapters; !THE NUMBER OF CHAPTERS ALREADY ON THE MASTER TAPE. epages = total epages; !THE COUNT OF THE EPAGES ON THIS TAPE. existing chapters=total chapters printstring(jtxt."Tape dump: requesting tape ".writetape." for dumping files.".snl) open mag(write unit, write tape."*") if chapters>0 start !THERE ARE FILES ALREADY ON THE TAPE, AS A CHECK READ VERIFY !THE TAPE UP TO THE END read verify(flag) if flag=1 start printstring("Verify: fails!".snl) ->unload finish finish else start !OTHERWISE WE ARE STARTING A NEW TAPE. skip mag(write unit, 1); !GET BEYOND THE LABEL write tm mag(write unit, flag) finish !WE ARE NOW POSITIONED READY TO WRITE THE NEW FILES. len = block for i=0, 1, block-1 cycle buffer(i)=0 repeat for i=0, 1, total indices cycle continue if index list(i)_identity="" !THIS IS A 'USED' INDEX. id char=index list(i)_id char index="JJ#".intostr(id char)."DEX" connect index(index, 3, index addr) for j=0, 1, index top cycle if index entry(j)_status=8 then disconnect(index, flag) c and exit !REACHED THE CURRENT TOP OF THE INDEX continue if index entry(j)_status#0 !THE FILE NEEDS TO BE WRITTEN OUT TO TAPE. filename="J".intostr(id char)."I" c .intostr(indexentry(j)_file id) connect(pdstore."_".file name, 0, 0, 0, r, flag) if flag#0 start printstring("Tape dump: ".filename." lost!!".snl) index entry(j)_status=9 !MARK THE FILE AS LOST. finish else start if epages>max epages start start new tape(flag) ->unload if flag=1 tape change=1 finish !THE MASTER TAPE IS FULL START NEW TAPE(OR OLD FULL ONE.) file length=integer(r_conad) file epages=file length>>12 if file epages<<12 # file length start last bytes=file length-file epages<<12 file epages=file epages+1 finish else last bytes=0 displ=0 chapters=chapters+1 chapter header_tape name<-write tape chapter header_username="JOURNL" chapter header_file name<-filename chapter header_date=date chapter header_time=time chapter header_type="JOURNAL" chapter header_chapter=chapters chapter header_epages=file epages chapter header_fsys=-1 chapter header_perms=0 write mag(write unit, wkaddr, len, flag) if flag#0 then c tape error("On writing file header in new chapter ".c intostr(chapters)." Fails:".intostr(flag)) c and ->unload !THE HEADER FOR THE FILE IS NOW WRITTEN. printstring(chapter header_tapename) printstring(" ".chapter header_file name) spaces(1); write(chapter header_chapter, 3) write(chapter header_epages, 4) newline epages=epages+1 !INCREMENT THE TOTAL EPAGE COUNT. for k=1, 1, file epages cycle if k=file epages and lastbytes>0 then c count=last bytes else count=block !NOW COPY OVER EACH PAGE OF THE FILE curraddr=r_conad+displ move(count, curraddr, wkaddr) write mag(write unit, wkaddr, len, flag) !ONE PAGE FROM THE FILE. displ = displ+block if flag#0 then tape error("On writing page ". c intostr(k)." of new chapter ".intostr(chapters). c " Fails:".intostr(flag)) and ->unload epages = epages+1 repeat write tmmag(write unit, flag) if flag#0 start printstring("Tape dump: failed to write tape mark at ") printstring("End of new chapter ") write(chapters, 4) and newline ->unload finish !FILE IS NOW ON THE TAPE OK, FILL IN INDEX FOR TAPE POSN. index entry(j)_tape<-write tape index entry(j)_chapter=chapters finish repeat disconnect(index, flag) repeat write tmmag(write unit, flag) if flag#0 start printstring("Tape dump: failed to write double tape mark.".snl) ->unload finish verify new chapters(existing chapters, chapters, flag) if flag=1 then ->unload !IE THE READ VERIFICATION FAILED. unload: unload mag(write unit) return if flag#0; ! Error at some stage in tape handling. !WE HAVE NOW CHECKED THAT THE NEW TAPE INFO CAN BE READ ALL THE WAY THROUGH. !UPDATE THE INDICES TO IDENTIFY THE POSITION OF THE FILE for i=0, 1, total indices cycle if index list(i)_identity#"" start id char=index list(i)_id char index="JJ#".intostr(id char)."DEX" connect index(index, 3, index addr) for j=0, 1, index top cycle if index entry(j)_status=0 then index entry(j)_status=1 !THE FILE IS NOW ON TAPE if tape change=1 start !THERE HAS BEEN AN ADDITION OF A NEW TAPE DURING THIS DUMP. if index entry(j)_tape=write tape and c index entry(j)_status>1 then index entry(j)_status=9 c and integer(index addr+x'2C')=cyclic(j, 1) !THE FILE WAS ON THE REUSED TAPE SO IT IS NOW LOST. ALSO !THE OLDEST FILE POINTER IS UPDATED. finish exit if index entry(j)_status=8 repeat disconnect(index, flag) finish repeat total epages=epages total chapters = chapters !AND AMEND THE CHAPTER COUNT AND PAGE COUNT. if tape change = 1 start !THERE WAS A CHANGE OF TAPE IN THIS DUMP. for i=1, 1, tape count cycle if tape cycle(i)_tsn=write tape then tape cycle(i)_age=-1 c and master entry=i if tape cycle(i)_tsn=full tape c then tape cycle(i)_age=relative age +1 repeat relative age=relative age+1 !INCREMENT THE BASE AGE COUNTER FOR TAPES. finish !WE HAVE COMPLETED THE TAPE DUMP SUCCESSFULLY system state=0; !IE TAPE DUMP COMPLETED OK. end ; !OF DUMP TO TAPE. routine file list from spooler integer id, dt, count, fsys string (16) name, s integer ld, hd, i, j, k, flag, dat, min, low, pass, pfcount ld=pack date and time("06/01/70", "01.01.01") hd=pack date and time("01/01/99", "01.01.01") string (16) file, spoolr file for count=0, 1, total indices cycle file list(count)_files=0 repeat !FIRST COLLECT ALL THE FILES FROM SPOOLER AND THROW OUT ANY !UNRECOGNISED FILES OR A MARKED BAD FILE. pf count=0 pass=0 if p file count>0 then pass=1 !If the last run failed then there may be files in Journal !that are waiting to be processed (pending files). !In the following section we deal with these files first followed !by files from Spooler (pass 1 and pass 0). cycle if pass=1 and pf count=p file count then pass=0 !WE HAVE LOOKED AT ALL THE PENDING FILES. if pass=1 start pf count=pf count+1 file=pending files(pf count) connect(pdstore, 3, 0, 0, r, flag) if flag #0 start printstring("Journal file 'JJ#PD' lost !!!") newline stop finish connect(pdstore."_".file, 0, 0, 0, r, flag) if flag#0 start printstring(jtxt."File ".file." lost!!!".snl) pending files(pf count)="" ->next finish finish else start req_dest=x'FFFF003C' req_flag=1 req_user="JOURNL" i=dpon2(spool, req, 1, 7) if poff file#"" start poff rep=0 dpoff(poff rep) if poff rep_flag#0 start printstring(jtxt."Warning, ".poff file) printstring(" still on queue, flag:") write(poff rep_flag, 3) and newline finish poff file="" finish if i#0 start printstring(jtxt."DPON2(3C) error..SPOOLR missing??".snl) stop finish repa==req; repb==req flag=0 if rep b_flag#0 then flag=rep b_flag else start if length(repb_file)=6 then spoolr file=rep b_file c else start flag=rep a_flag spoolr file=rep a_file if flag=0 finish finish file=spoolr file if flag=0 exit if flag=207 if flag#0 start printstring(jtxt."Failed, Spooler flag: ") write(flag, 3) and newline printstring(" whilst accessing JOURNL queue.".snl) stop finish fail file=spool.".".file if file=bad file start !THIS FILE HAS BEEN MARKED AS BAD AND IS TO BE IGNORED AND REMOVED. disconnect(spool.".".file, flag) remove queued file(file) printstring(jtxt."File ".bad file." removed!".snl) bad file="" ->next finish !FIND THE FILE SYSTEM FOR THIS SPOOLR. s=file; length(s)=2 fsys = s to i(s) unless 0<=fsys<=nsys start printstring(jtxt."Invalid fsys for file: ".fail file) printstring(" , removing queue entry".snl) remove queued file(file) ->next finish i=(fsys<<8)!x'80' connect(spool.".".file, 0, 0, i, r, flag) if flag#0 start printstring(jtxt."Cannot connect ".fail file." flag") write(flag, 3) and newline remove queued file(file) ->next finish if integer(r_conad+8)&x'0FFF'#0 or integer(r_conad) c >x'100000' start printstring(jtxt."File SPOOLR.".file." has a corrupt") printstring(" Header or is too big(>1024k), file discarded.".snl) sdisconnect(spool.".".file, fsys, flag) remove queued file(file) ->next finish if r_datastart=r_dataend or r_dataend>integer(r_conad+8) c or r_dataend<r_datastart start !THE FILE IS EMPTY OR HAS A BAD HEADER. sdisconnect(spool.".".file, fsys, flag) remove queued file(file) printstring(jtxt."Throwing out empty/bad file ".file.snl) ->next finish flen=r_dataend !IT IS WORTH NOTING HERE THAT THE PD FILE CAN HOLD UP TO !4 MEG. SINCE SPOOLER ONLY HOLDS 100 FILES IT WILL BE UNLIKELY !THAT THE AVERAGE FILE SIZE WILL EXCEED 40K SO A SINGLE RUN !IS EXTREMELY UNLIKELY TO FILL THE PARTITION ESPECIALLY !SINCE RUNS WILL CATCH THE QUEUE WELL BEFORE THE UPPER FILE !LIMIT IS REACHED. printstring(jtxt."Taking ".file." from ".spool) newline file="J".file copy(spool.".".spoolr file.",".pdstore."_".file) connect(pdstore, 3, 0, 0, r, flag) monitor if flag # 0 connect(pdstore."_".file, 0, 0, 0, r, flag) if flag#0 start printstring(jtxt."Fails taking file from queue.".snl) printstring(" see documentation, failure number 2.".snl) ss=" JOURNAL SYSTEM FAILS FAILURE NO: 2." byteinteger(addr(ss)+1)=17 oper(0, ss) autoflag=off; fail type=2 sdisconnect(spool.".".spoolr file, fsys, flag) requeue file(spoolr file) stop finish !THE FILE HAS BEEN SUCCESSFULLY COPIED INTO JOURNL. sdisconnect(spool.".".spoolr file, fsys, flag) remove queued file(spoolr file) fail file="" finish id=integer(r_conad+x'18') dt = dtword(integer(r_conad+x'14')) ! Note that date in logfile header is STILL in old format (put there by Director). if id&x'FF' = 0 then integer(r_conad+4)=x'20' !TO GET ROUND PETES FAULT IN SUPERV. flag=0 if (id>>8)=x'FFFFFF' start id=x'FF'&id if 0<=id<=total indices start flag=1 if ld<=dt<=hd then flag=2 !IE IS THE DATE AND TIME OK FOR RANGE? finish finish if flag=2 start if index list(id)_identity#"" start !WE RECOGNISE THE FILE file list(id)_files=file list(id)_files+1 count=file list(id)_files file list(id)_names(count)<-file file list(id)_dts(count)=dt if pass=0 start !ONLY ADD FILE TO PENDING LIST IF NEWLY OFF SPOOLER. p file count=p file count+1 pending files(p file count)=file finish if count=100 start printstring(jtxt."Filled file space, ") printstring("Commencing processing!!".snl) printstring(" Some files will be unordered!!!!".snl) exit finish finish else start printstring(jtxt.file." not recognised !!".snl) printstring(" type ".intostr(id)." invalid.".snl) finish finish else start if flag=0 then c printstring(jtxt.file." not a 'JOURNAL' file!!".snl) if flag=1 start printstring(jtxt.file." has bad date/time entry!!".snl) spaces(10) printstring(unpackdate(dt)." ".unpacktime(dt).snl) finish newlines(2) send(file.",.LP"); !SEND TO PRINTER IF INVALID FILE. finish next: repeat !Now sort each queue of pending files into chronological order. for i=0, 1, total indices cycle fli == file list(i) count=fli_files continue if count=0 for j=1, 1, count-1 cycle low=j; min=fli_dts(j) for k=j+1, 1, count cycle if fli_dts(k)<min start min=fli_dts(k) low=k finish repeat if low#j start name=fli_names(low) dat=fli_dts(low) fli_names(low) = fli_names(j) fli_dts(low)=fli_dts(j) fli_names(j) = name fli_dts(j) = dat finish repeat printstring("Index: ".intostr(i));newline for j=1, 1, count cycle printstring(fli_names(j)." ". c unpackdate(fli_dts(j))." ". c unpacktime(fli_dts(j))) newline repeat repeat end ; !OF FILE LIST FROM SPOOLR. routine check file(string (*)name file, byteintegername c data type, integername flag) !THE ROUTINE LOOKS FOR DATE AND TIME INFORMATION IN THE FILE integer word count, i ! routine reverse line to atoms(integername word count, stringarrayname atoms, byteintegerarrayname buff) !HERE WE READ A LINE OF THE FILE INTO AN ARRAY OF "ATOMS" PASSING !BACK THE RESULTING WORDS(WORD COUNT DEFINING THE NUMBER OF WORDS) !IN THE ARRAY ATOM. integer adn byteinteger ch, i word count=0; endflag=0; i=0 cycle chpointer=chpointer-1 if chpointer<flen then endflag=1 and return ch=buff(chpointer) exit if ch>32 repeat cycle if ch=32 or ch=10 start if i>0 then byteinteger(adn)=i and i=0 return if ch=10 finish else start if 32<ch<128 start if i=0 start word count=word count+1 unless word count=68 adn=addr(atoms(word count)) finish i=i&x'7F'+1 !LENGTH OF ATOM SHOULD NOT EXCEED 127, SET TO 1 IF OCCURS!! byteinteger(adn+i)=ch finish finish chpointer=chpointer-1 if chpointer<flen then endflag=1 and ch=10 c else ch=buff(chpointer) repeat end ; !OF REVERSE LINE TO ATOMS. start date="" fail file=file connect(pdstore."_".file, 0, 0, 0, r, flag) if flag#0 start printstring(jtxt."Cannot connect ".file." for date search!".snl) stop finish if datatype=1 or integer(r_conad+x'18')&x'FF'=5 start !IE WITH A MAPPED DATE FILE OR BACKUP/ARCHIVE REPORT FILE WE KNOW THAT !THE DATE INFORMATION IS THAT CONTAINED IN WORD 6 OF THE HEADER. start date="*" finish date=unpack date(integer(r_conad+x'14')) finish time=unpack time(integer(r_conad+x'14')) disconnect(pdstore."_".file, flag) flag=0 fail file="" return finish buff==array(r_conad+r_datastart, af buff) flen=r_dataend-r_datastart chpointer=0 cycle line to atoms(word count, atoms, buff) exit if endflag=1 if word count>=3 start if atoms(1)="DT:" start start date=atoms(2) start time=atoms(3) exit finish if atoms(1)="SDT:" start finish date=atoms(2) finish time=atoms(3) start date="*" exit finish finish repeat unless start date="*" start finish date=start date finish time=start time chpointer=flen flen=1 cycle reverse line to atoms(word count , atoms, buff) exit if endflag=1 if word count>=3 and atoms(word count)=":TD" start if length(atoms(word count-1))=length(atoms(word count-2))=8 c start for i=8, -1, 1 cycle byteinteger(addr(finish date)+9-i) c =byteinteger(addr(atoms(word count-1))+i) byteinteger(addr(finish time)+9-i)= c byteinteger(addr(atoms(word count-2))+i) repeat length(finish time)=8 length(finish date)=8 exit finish finish repeat finish disconnect(pdstore."_".file, flag) fail file="" flag=0 end ; !OF CHECK FILE. routine remove queued file(string (6) file) !HERE WE TELL SPOOLER TO REMOVE THE SPECIFIED FILE, IE DELETE IT, FROM !ITHE JOURNAL QUEUE. integer i req_dest=x'FFFF003D' req_flag=0 req_user="JOURNL" req_file<-file i=dpon2(spool, req, 1, 6) if i#0 start printstring(jtxt."DPON2(3D) error..SPOOLR missing??".snl) stop finish poff file=file end ; !OF REMOVE QUEUED FILE. routine requeue file(string (6) file) !HERE WE REQUEUE A FILE AFTER A PROBLEM. integer i req_dest=x'FFFF003D' req_flag=1 req_file<-file req_user="JOURNL" i=dpon2(spool, req, 1, 7) if i#0 start printstring(jtxt."DPON(3D) error, SPOOLR missing??".snl) stop finish repa==req; repb==req flag=repb_flag if flag #0 start printstring(jtxt."File: ".file." cannot requeue!".snl) finish return end ; !OF REQUEUE FILE integerfn autojob(string (15) name, string (*)name ident) !THIS ROUTINE INTERROGATES SPOOLR TO SEE IF THERE IS A BATCH JOB !'NAME' IN THE QUEUE AND PASSES BACK ITS IDENTITY. recordformat fhf(integer end, start, size, type, spare0, datetime, spare1, spare2) recordformat infof(integer vsn, state, string (7) ident, user, string (15) dest, srce, output, string (31) name) string (63) message record (infof)name info record (fhf)name fh record (f parm)p integer i, entries, flag destroy("JJINF", flag) message="COMMAND QUEUE BATCH,JJINF" p=0 flag=dspool(p, length(message), addr(message)+1) if flag#0 start printstring("SPOOLR fault: no access!!".snl) respool journal("MONITOR") stop finish connect("JJINF", 0, 0, 0, r, flag) if flag#0 start printstring("Cannot connect SPOOLR info file for 'AUTOJOB'".snl) respool journal("MONITOR") stop finish fh==record(r_conad) ident="" entries=(fh_end-fh_start)//256 result =no if entries=0 for i=1, 1, entries cycle info==record(r_conad+32+(i-1)*256) if info_name=name and info_state=1 then ident = info_ident and result =yes repeat result =no end ; !OF AUTOJOB. routine respool journal(string (15) name) !This routine is used to detach the auto command file that controls !the Journal system in background mode. The detached files start Journal !automatically every hour. string (255) msg integer flag string (8) tt, th, timereq; integer hours, j, ocptype connect("JENGPD_JENGHD", 0, 0, 0, r, flag) ocptype=16 if flag=0 start if 0<=integer(r_conad+x'100')<=15 then c ocptype=integer(r_conad+x'100') finish if name = "HOUSEKEEP" then timereq=ocptimereq(ocptype) else timereq = "10" define("STREAM12,JCMDFILE") select output(12) msg = "JOURNAL(AUTOCALL" if name = "HOUSEKEEP" then msg = msg."+DECK)" else msg = msg.")" if uinfi(16)=0 start ; ! NOBRACKETS option in force. charno(msg,8) = ' ' length(msg) = length(msg)-1 finish printstring(msg) newline select output(0) close stream(12) disconnect("JCMDFILE", flag) msg="DOCUMENT DEST=BATCH,USER=JOURNL, PASS=".back pass.", " msg=msg."SRCE=JCMDFILE,TIME=".timereq.",PRTY=VHIGH,NAME=".name."," tt=time tt->th.(".").tt hours = s to i(th) hours=hours+1 if hours=24 then tt="23.59.59" else start th=intostr(hours) if length(th)=1 then th="0".th tt=th.".".tt finish if name = "HOUSEKEEP" then msg=msg."DECKS=1" else c msg=msg."AFTER=".date." ".tt msg = msg.",OUT=FILE,OUTNAME=JJLOG".tostring('0'+nextjjlog) msg = msg.",RERUN=NO " p=0 j=0 j=dspool(p, length(msg), addr(msg)+1) if j#0 start printstring("Cannot spool auto command file(".name.") flag:") write(j, 3) and newline ss=" JOURNAL SYSTEM FAILS FAILURE NO: 3." byteinteger(addr(ss)+1)=17; ! Flashing. fail type=3 autoflag=off oper(0, ss) finishelse nextjjlog = (nextjjlog+1)&7; ! Thus 0<=nextjjlog<=7. end ; !OF RESPOOL JOURNAL routine start up !The system state setting from the last run of Journal is looked at !and based on this a decision is made on the route for the startup of !this run. integer i, j conststring (7)array fail anal(4:7) = "MAINLOG","SPOOLR","VOLUMS","DIRECT" switch sw(0:4) if autocall = on and autoflag = off start !THIS IS AN AUTOMATIC CALL OF JOURNAL BUT IT CANNOT !PROCEED BECAUSE THE AUTO FLAG HAS BEEN SET TO INDICATE AN ERROR !CONDITION IS PRESENT FROM THE LAST RUN. ss=" JOURNAL IN FAIL STATE" ss=ss." FAILURE NO: ".intostr(fail type) byteinteger(addr(ss)+1)=17 oper(0, ss) printstring(jtxt."Fail state ".intostr(fail type)) printstring(" recorded on oper!".snl) stop finish if autocall=on start !OK TO PROCEED WITH AUTOMATIC RUN OF JOURNAL. printstring("Automatic Journal run.".snl) j=minutes between(run date, packdateandtime(date, time)) flag=0 !TEST A: >=24 HRS SINCE LAST RUN AND >16K BYTES IN QUEUE. if j>=24*60 and queue_amount>16*1024 then flag=1 !TEST B: >=25 FILES IN QUEUE OR >0.8 MEG OF FILES IN QUEUE. if queue_amount>(800*1025) or queue_length>=25 c then flag=1 !TEST C:(FOR PRIME TIME ONLY)>=45 FILES OR >2 MEG OF FILES if queue_amount>(2000*1024) or queue_length>=45 c then flag=2 printstring("SPOOLR parameters:".snl) printstring("Files:"); write(queue_length, 3) and newline printstring("Total size:"); write(queue_amount, 6) and newline printstring("Minutes since last run:"); write(j, 5) and newline if prime start<packdate and time(date, time)<prime end start printstring("We are in prime period.".snl); newline flag=0 if flag=1 finish if system state#0 start printstring(jtxt."Last run incomplete, or failed") printstring(" (system crash?).".snl) printstring("Running again to clear problem.".snl) flag=1 finish if flag>=1 start !WE WANT A FULL RUN. if decks = on then printstring("**Commencing auto run**".snl) C else start !DETACH THE JOB TO DO THE FULL RUN. respool journal("HOUSEKEEP") if autojob("HOUSEKEEP", identj)=off printstring("Full run detached or already there.".snl) if identj = "" then flag = autojob("HOUSEKEEP", identj) !FIND OUT THE IDENTITY IF JUST QUEUED. flag = 0 ss=" JOURNAL RUN REQUIRED " ss=ss." RUN ".identj." SOON!" byteinteger(addr(ss)+1)=17 oper(0, ss) finish finish else printstring("**Full run not required**".snl) stop if flag=0 finish run date=pack date and time(date, time) ->sw(system state) sw(0): !ALL OK IN THE LAST RUN. if fail type<4 start printstring(jtxt."Last run of Journal ended normally ".snl) finish else start printstring(jtxt."Last run completed housekeeping but the".snl) printstring("auto ".fail anal(failtype)." analysis failed!!".snl) finish return sw(1): printstring(jtxt."Restarting from Spooler unloading") printstring(" failure during previous run".snl) if fail file#"" start printstring(jtxt."File: ".fail file." error warning!".snl) finish else start printstring(jtxt."No file in error, probably system crash?".snl) finish !TRIM DOWN THE PENDING FILE LIST(IE THOSE FILES LEFT OVER FROM FAILURE !OF THE LAST RUN.) if p file count>0 start i=0 cycle i=i+1; exit if i=p file count+1 if pending files(i)="" start if i=p file count then p file count=p file count-1 c and exit for j=i+1, 1, p file count cycle pending files(j-1)=pending files(j) repeat p file count=p file count-1 i=i-1 finish repeat finish system state=2 !ALLOW RESTART run tape=1 return sw(2): printstring(jtxt."Last run skipped tape dump.".snl) run tape=1 return sw(3): if tapeskip=1 start if external=off start printstring(jtxt."The tape dump failed last run.".snl) printstring(" Skip option not valid after failure!".snl) stop finish else start !IE CALL FROM 'FULL JOURNAL ANALYSIS' ALLOWED TO RUN !FILE COLLECTION EVEN THOUGH THERE WAS A TAPE CONTINGENCY !ON THE LAST RUN. THE CONTINGENCY WILL BE RETAINED(UNLESS OF !COURSE THE FILE COLLECTION FAILS AND THIS HIGHER PRIORITY !CONTINGENCY IS THEN REMEMBERED) printstring(jtxt."Last run failed in tape dump".snl) printstring(" Allowing file collection run for 'FULL") printstring(" Journal analysis'".snl) system state=3 return finish finish run tape=1 printstring(jtxt."The tape dumping failed last run.".snl) if autocall=on start printstring(" Must have been system crash, proceeding ") printstring("with file collection.".snl) system state=2 finish else start printstring(" Retrying the tape dump.".snl) system state=4 finish return sw(4): !SHOULD NOT RETURN HERE EXCEPT IN FLUKE "SYSTEM DOWN" SITUATION. !SHOULD TREAT THIS AS SW(3) TYPE ASSUMING TAPE DUMP TO BE RETRIED. printstring(jtxt."Retrying tape dump.".snl) run tape=1 return end ; !OF START UP. end ; !OF JOURNAL ! ************************************************************************ ! ************************************************************************ ! ************************************************************************ externalroutine journal state(string (255) s) record (f queue)name queue record (f tape cycle)arrayformat af tape cycle(1:100) record (f tape cycle)arrayname tape cycle record (rf)r integer j, i, status, flag, autoflag, fail type, queues, k, latedate string (8) tdate, ttime newpage printstring("Journal status report ".date." ".time) newline connect(control, 0, 0, 0, r, flag) if flag#0 then master file failure(control, flag) status=integer(r_conad+x'24') autoflag=integer(r_conad+x'6DC') fail type=integer(r_conad+x'6D8') tdate=unpack date(integer(r_conad+x'20')) ttime=unpack time(integer(r_conad+x'20')) printstring("Last run on ".tdate." at ".ttime);newline j = -1; latedate = 0 for i=0,1,7 cycle connect("JJLOG".tostring('0'+i), 0, 0, 0, r, flag) continue if flag#0 k = integer(r_conad+20)&x'7FFFFFFF'; ! Time last changed. j = i and latedate=k if k>latedate repeat if j=-1 then printstring("No autojob logfiles found") else c printstring("Last autojob logfile: JJLOG".tostring('0'+j)) newlines(2) printstring("Status details: ") if autoflag=1 start if status=0 start printstring("In automatic housekeeping mode.");newline printstring("Action required: none.");newlines(2) finish else start printstring("Last auto housekeeping failed, recovery will ") newline; printstring(" be attempted automatically.") newline; spaces(16);printstring("[") printstring(journal status(status)."]");newline printstring("Action required: none.");newlines(2) finish finish else start if fail type=0 start printstring("In manual mode with an unexplained error or after") newline;printstring(" a System crash.");newline spaces(16);printstring("[") printstring(journal status(status)."]") newline printstring("Action required: JOURNAL OVERRIDE in JOURNL process.") newlines(2) finish else start printstring("In manual mode due to failure, doc ref: ") write(failtype, 2);newline; printstring("Action required: ") printstring("see Journal documentation.");newlines(2) finish finish connect(spool.".CFILE", 9, 0, 0, r, flag) if flag#0 start !WE CANNOT CONNECT THE SPOOLR INFO FILE. printstring("Spoolr descriptor file (CFILE) connect fails:") write(flag, 3); newline printstring("Log off and try again.") newline stop finish queues=integer(r_conad+x'18') if queues=0 start printstring("No queues defined in SPOOLR descriptor file") newline finish for i=1, 1, queues cycle queue==record(r_conad+x'20'+148*(i-1)) if queue_name="JOURNAL" then exit if i=queues start printstring("Journal queue not in SPOOLR descriptor file") newline finish repeat printstring("Current state of the 'JOURNAL' queue:");newline printstring("Files:"); write(queue_length, 3) printstring(" Total bytes:"); write(queue_amount, 6) newline connect(control, 0, 0, 0, r, flag) if flag#0 then master file failure(control, flag) !NOW ADD THE DETAILS FROM THE TAPE CONTROL . j=0 newline printstring("Tape cycle: there are ");write(integer(r_conad+x'700'), 3) printstring(" tapes in the cycle.") newline if integer(r_conad+x'700')>0 start !THERE ARE TAPES IN THE CYCLE TO DESCRIBE. tape cycle==array(r_conad+x'720', af tape cycle) if integer(r_conad+x'708')>0 start !THERE IS AN ASSIGNED MASTER , IE. SYSTEM IN USE. printstring("Master tape: ") printstring(tape cycle(integer(r_conad+x'708'))_tsn) printstring(" with a total of "); write(integer(r_conad+x'710'), 4) printstring(" chapters, "); write(integer(r_conad+x'714'), 4) printstring(" epages.") newline finish newline; printstring("Full tape cycle list:") newline for i=1, 1, integer(r_conad+x'700') cycle j=j+1 printstring("TSN:".tape cycle(i)_tsn." ") if tape cycle(i)_age=-1 then printstring("master tape") if tape cycle(i)_age=0 then printstring("unused tape") if tape cycle(i)_age>0 then printstring("full tape ") if j=3 then newline and j=0 else spaces(3) repeat finish newlines(2) printstring("End of system summary.") newline disconnect(control, flag) end ; !OF JOURNAL STATE. ! ************************************************************************ ! ************************************************************************ externalroutine list journal index(string (255) s) ! Parameter can be "dd/mm/yy,dd/mm/yy" (either or both optional), to ! specify the range of files of interest. record (f index entry)arrayformat af index entry(0:index top) record (f index list)arrayformat af index list(0:total indices) record (f index entry)arrayname index entry record (f index entry)name ie record (f index list)arrayname index list record (rf)r conststring (40) array status description(0:9)= c "ON LINE", "ON LINE AND ON TAPE: ", " ON TAPE: ", "", "", "", "", "", "", "LOST!!!!!!!!!" string (8) index, tdate, ttime string (16) reply byteinteger id, data type integer i, flag, status, entry, lost flag, early, late connect(control, 0, 0, 0, r, flag) if flag#0 then master file failure(control, flag) index list==array(r_conad+x'30', af index list) early = pack date and time("01/01/72","00.00.00") late = current packed dt if s#"" start ; ! Date range specified. if s -> s.(",").reply start if length(reply)=8 and charno(reply,3)='/' and charno(reply,6)='/' c then late = pack date and time(reply,"23.59.59") finish if length(s)=8 and charno(s,3)='/' and charno(s,6)='/' then c early = pack date and time(s,"00.00.00") finish if early>late start printstring(jtxt."Early date is after late date??") newline return finish cycle !Find out which file is to be listed. prompt("INDEX KEYWORD:") read prompt reply(reply) if reply="HELP" start printstring(jtxt."Current index keywords:"); newlines(2) for i=0, 1, total indices cycle !LIST OUT THE INDEX KEYWORDS. if index list(i)_identity#"" then c printstring(index list(i)_identity) and newline repeat return finish identify index(reply, id, data type, entry) !FIND THE IDENTITY CHARACTER OF THIS INDEX. exit if id#100 printstring(jtxt."Reply help for a list of keywords") newline repeat index="JJ#".intostr(id)."DEX" !THE INDEX FILE connect(index, 0, 0, 0, r, flag) if flag#0 then master file failure(index, flag) define("STREAM10,JLIST,1024") select output(10) printstring(jtxt."List of index ".index.". ".date." ".time) newline printstring("===================================================") newlines(2) printstring("Date range: ".unpackdate(early)." - ".unpackdate(late)) newlines(2) printstring("Index keyword: ".reply) newlines(3) lost flag = 0; ! Used to prevent repeated "file lost" output. index entry==array(r_conad+x'40', af index entry) for i=0, 1, index top cycle ie == index entry(i) exit if ie_file id=-1 ! IE THE CURRENT TOP OF THE INDEX. continue if ie_finishing<early or ie_starting>late; ! File not in requested range. if ie_status=9 start if lost flag=1 start printstring(" ..... all lost up to .....") newline finish lost flag = lost flag+1 continue if lost flag>1 finish else lost flag = 0 printstring("File: ") write(ie_file id, 5) tdate=unpack date(ie_starting) ttime=unpack time(ie_starting) printstring(" ".tdate." ".ttime." to ") tdate=unpack date(ie_finishing) ttime=unpack time(ie_finishing) printstring(tdate." ".ttime." status: ") status=ie_status printstring(status description(status)) if 1<=status<=2 then printstring(ie_tape) c and printstring("(".intostr(ie_chapter).")") newline repeat newlines(2) printstring(jtxt."End of list of index: ".index) newlines(3) select output(0) close stream(10) printstring(jtxt."List prepared in JLIST.") newlines(2) disconnect(index, flag) disconnect(control, flag) end ; !OF LIST JOURNAL INDEX ! ************************************************************************ ! ************************************************************************ ! ************************************************************************* externalroutine new journal index(string (255) s) !STRING S WILL ONLY BE SET WHEN THE ROUTINE IS CALLED FROM !"CREATE JOURNAL SYSTEM" WITH S='SYSTEM'. IN THIS CASE ALL THE SYSTEM !INDICES ARE INITIALISED. ON A NORMAL CALL S IS NOT SET AND A SET !OF PROMPTS ARE USED TO DEFINE THE INDEX TO BE SET UP. record (f index list)arrayformat af index list(0:total indices) record (f index entry)arrayformat af index entry(0:index top) record (f index list)arrayname index list record (f index entry)arrayname index entry record (rf)r integer i, j, k, flag, entry, data string (16) reply, dtype byteinteger id char, data type integerfn empty slot(integer type) !FIND THE NEXT EMPTY INDEX SLOT IN JJMASTER THAT WILL !DEFINE THE IDENTITY OF THE NEW INDEX. integer i, j if type=0 then j=0 else j=system indices+1 for i=j, 1, total indices cycle if index list(i)_identity="" then result =i repeat result =-1 end ; !OF EMPTY SLOT. routine new index(byteinteger id char, integername flag) !CREATE AND INITIALISE A NEW INDEX DEFINED BY ID CHAR !FLAG=0: SUCCESS, FLAG=1: FAILURE. record (f index entry)name ie0 string (8) file integer i, conad, cflag file="JJ#".intostr(id char)."DEX" flag=1; !DEFAULT FAILURE. connect(file, 0, 0, 0, r, cflag) if cflag=0 start printstring(jtxt.file." already exists") newlines(2) return finish create jfile(file, index top+1 {cells}, 24 {cell size}, x'40' {header}, conad, cflag) if cflag#0 start printstring(jtxt."Cannot create ".file." flag:") write(cflag, 3) newlines(2) return finish integer(conad+x'20')=0; !NEXT FREE INDEX ENTRY, ALSO USED AS POINTER TO LAST(+1) FILE FOR AUTO ANALYSIS. integer(conad+x'24')=0; !NEXT FREE SEQUENCE NO. integer(conad+x'28')=0; !NEXT FILE ENTRY TO BE PROCESSED BY AUTO ANAL. integer(conad+x'2C')=0; !The oldest file on the index pointer. index entry==array(conad+x'40', af index entry) ie0 == index entry(0) ie0_file id=-1 ie0_starting = current packed dt ie0_finishing=ie0_starting ie0_status=8 ie0_chapter=-1 ie0_tape="" index entry(i) = ie0 for i=1,1,index top disconnect(file, flag) cherish(file) printstring(jtxt."File recognition number for ".file." is: ") write(id char, 3) newline flag=0; !SUCCESSFUL. end ; !OF NEW INDEX connect(control, 3, 0, 0, r, flag) if flag#0 then master file failure(control, flag) index list==array(r_conad+x'30', af index list) !THE INDEX CONTROL LIST. if s="SYSTEM" start !A CALL FROM 'CREATE JOURNAL SYSTEM' TO INITIALISE SYSTEM INDICES. for i=0, 1, used system indices cycle !CREATE EACH OF THE SYSTEM INDICES. j=empty slot(0) !THE NEXT EMPTY INDEX SLOT. if j#i start !NO INDICES SHOULD ALREADY EXIST. printstring(jtxt."Severe warning, do not attempt ") printstring("to recreate system indices!!!") newlines(2) disconnect(control, flag) return finish id char=index list(j)_id char !THE IDENTITY CHARACTER OF THE NEW INDEX. new index(id char, flag) if flag#0 start printstring(jtxt."Failed to create system index!") newline for k=1, 1, i cycle exit if k=i destroy("JJ#".intostr(index list(k)_id char)."DEX", flag) !DESTROY ALL THE ALREADY CREATED SYSTEM INDICES. index list(k)_identity="" repeat disconnect(control, flag) destroy(control, flag) !DESTROY JJMASTER AS WELL TO GIVE CLEAN RETRY. printstring(jtxt."Try running create again after checking") printstring(" over the process") newlines(3) stop finish index list(j)_identity<-system keyword(i) index list(i)_data type=0; !DEFAULT VALUE OF 'TEXT'. if system keyword(i)="ACCOUNTS" then index list(i)_data type=1 !IE THIS IS A MAPPED DATA TYPE FILE. printstring(jtxt.system keyword(i)." index initialised") newlines(2) repeat printstring(jtxt."All system indices created.") newlines(3) disconnect(control, flag) return finish ; !OF "SYSTEM" JOURNAL INDICES CREATION. !BELOW CODE WILL ADD INSTALLATIONS OWN INDEX. !WHICH WILL BE INDICES 10-19, OR IT WILL BE USED !TO ADD A NEW SYSTEM INDEX (RANGE 0-9) cycle prompt("SYS OR OWN:") read prompt reply(reply) exit if reply="SYS" or reply="OWN" repeat if reply="SYS" then j=empty slot(0) else j=empty slot(1) cycle prompt("INDEX KEYWORD:") read prompt reply(reply) exit if 0<length(reply)<=12 printstring(jtxt.reply." too long??") newlines(2) repeat data=-1 cycle prompt("TEXT OR MAPPED:") read prompt reply(dtype) data=0 if dtype="TEXT" data=1 if dtype="MAPPED" exit if data#-1 repeat if j=-1 start printstring(jtxt."System full, no further indices.") newlines(2) return finish identify index(reply, id char, data type, entry) if id char<100 start printstring(jtxt."Keyword already used!!") newlines(2) return finish id char = index list(j)_id char new index(id char, flag) !CREATE THE NEW INDEX DEFINED BY ID CHAR. if flag#0 start printstring(jtxt."Failed to create ".reply." index!") newlines(2) return finish index list(j)_identity<-reply index list(j)_data type<-data !FILL IN THE KEYWORD NOW INDEX CREATED. printstring(jtxt.reply." index initialised.") newlines(3) disconnect(control, flag) end ; !OF NEW JOURNAL INDEX. ! ************************************************************************ ! ************************************************************************ ! ************************************************************************ externalroutine new journal tape(string (255) s) record (f tape cycle)arrayformat af tape cycle(1:100) record (f tape cycle)arrayname tape cycle record (rf)r integer i, flag integername tape count string (16) reply !THE CONTROL MASTER FILE. connect(control, 3, 0, 0, r, flag) !WE WANT TO WRITE TO IT. if flag#0 then master file failure(control, flag) tape count==integer(r_conad+x'700') !THE TOTAL TAPES IN THE CYCLE. cycle !GET THE TAPE IDENTITY TO BE ADDED TO THE CYCLE. prompt("JOURNAL TAPE:") read prompt reply(reply) if length(reply)=6 then exit !CORRECT LENGTH TSN. repeat tape cycle==array(r_conad+x'720', af tape cycle) if tape count=0 start !THERE ARE NO TAPES ON CYCLE AT THE MOMENT. tape cycle(1)_tsn<-reply tape cycle(1)_age=0 tape count=1 finish else start !THERE ARE TAPES ALREADY IN THE CYCLE. for i=1, 1, tape count cycle !CHECK TAPE NOT ALREADY THERE. if tape cycle(i)_tsn=reply start printstring(jtxt.reply." already in cycle") newlines(2) return finish repeat for i=1, 1, 100 cycle !NOW SLOT IN THE NEW TAPE. if tape cycle (i)_tsn="" start !WE HAVE FOUND EMPTY SLOT. tape cycle(i)_tsn<-reply tape cycle(i)_age=0; !UNUSED. tape count=tape count+1 exit finish repeat finish printstring(jtxt.reply." added to cycle with new total of ") write(tape count, 2) printstring(" tapes.") newlines(2) disconnect(control, flag) end ; !OF NEW JOURNAL TAPE. ! ************************************************************************ ! ************************************************************************ ! ************************************************************************ externalroutine remove journal index(string (255) s) record (f index list)arrayformat af index list(0:total indices) record (f index list)arrayname index list record (rf)r string (16) reply byteinteger id char, data type integer flag, entry cycle !FIND THE IDENTITY OF THE INDEX TO BE REMOVED. prompt("INDEX KEYWORD:") read prompt reply(reply) exit if 0<length(reply)<=12 printstring(jtxt.reply." too long??") newlines(2) repeat identify index(reply, id char, data type, entry) if id char=100 start printstring(jtxt.reply." not valid keyword") newlines(2) return finish connect(control, 3, 0, 0, r, flag) if flag#0 then master file failure(control, flag) index list==array(r_conad+x'30', af index list) index list(entry)_identity="" !THE INDEX ENTRY IS REMOVED. destroy("JJ#".intostr(id char)."DEX", flag) disconnect(control, flag) printstring(jtxt."Index removed.") newlines(2) end ; !OF REMOVE JOURNAL INDEX ! ***************************************************************************** ! ***************************************************************************** ! ***************************************************************************** externalroutine journal backpass(string (255) s) externalintegerfnspec dsetpassword(string (6) user, integer fsys, which, string (63) old, new) string (63) forepass, backpass record (rf) r integer i, flag connect(control, 3, 0, 0, r, flag) if flag#0 start printstring("Unable to connect ".control) newline return finish printstring("Background password currently stored by Journal: ".c string(r_conad+x'27D0')) newline printstring("If this is satisfactory, exit by replying '*' to the first prompt.") newlines(2) printstring("Give current foreground password, then new background password.") newline for i = 1,1,3 cycle prompt("Foreground:") read prompt reply(fore pass) flag = 1 and exit if fore pass="*" prompt("New back:") read prompt reply(back pass) if length(back pass)>11 start printstring("**Warning: reduced to first 11 characters.") newline length(back pass) = 11 finish flag = dsetpassword("JOURNL",-1,1,fore pass, back pass) exit if flag=0 printstring("Failed!! You get 3 tries. That was try no.") write(i,1); newline repeat if flag#0 start printstring("Background password unchanged.") finishelsestart string(r_conad+x'27D0') = back pass printstring("New background password now in use.") finish newline end ; ! Of %external %routine journal backpass. !************************************************************************** ! ROUTINES AND FUNCTIONS COMMON TO THE SYSTEM. !************************************************************************** routine identify index(string (*)name keyword, byteintegername c id char, data type, integername entry) !HERE WE ARE GIVEN AN INDEX IDENTITY KEYWORD IE 'ERRORLOG' AND !WE SEARCH TO SEE IF IT IS VALID, IF IT IS WE PASS BACK THE !IDENTITY OF THE INDEX IN THE RANGE '0' TO '99' WHICH DEFINES THE !INDEX IE JJ'8'DEX ELSE WE PASS BACK A DEFAULT FAIL VALUE OF -1. record (f index list)arrayformat af index list(0:total indices) record (f index list)arrayname index list record (rf)r string (16) file integer i, flag file="JJMASTER" connect(file, 0, 0, 0, r, flag) if flag#0 then master file failure(file, flag) index list==array(r_conad+x'30', af index list) for i=0, 1, total indices cycle if index list(i)_identity=keyword start id char=index list(i)_id char data type=index list(i)_data type entry=i return finish repeat id char=100; !IE FAILED TO FIND MATCHING KEYWORD. end ; !OF IDENTIFY INDEX. routine line to atoms(integername word count, stringarrayname atoms, byteintegerarrayname buff) !HERE WE READ A LINE OF THE FILE INTO AN ARRAY OF "ATOMS" PASSING !BACK THE RESULTING WORDS(WORD COUNT DEFINING THE NUMBER OF WORDS) !IN THE ARRAY ATOM. integer adn byteinteger ch, i word count=0; endflag=0; i=0 cycle chpointer=chpointer+1 if chpointer>flen then endflag=1 and return ch=buff(chpointer) exit if ch>32 repeat cycle if ch=32 or ch=10 start if i>0 then byteinteger(adn)=i and i=0 return if ch=10 finish else start if 32<ch<128 start if i=0 start word count=word count+1 unless word count=68 adn=addr(atoms(word count)) finish i=i&x'7F'+1 !LENGTH OF ATOM SHOULD NOT EXCEED 127, SET TO 1 IF OCCURS!! byteinteger(adn+i)=ch finish finish chpointer=chpointer+1 if chpointer>flen then endflag=1 and ch=10 c else ch=buff(chpointer) repeat end ; !OF LINE TO ATOMS. routine master file failure(string (*)name file, integer flag) !HERE WE PRINT THE WARNING OF A FAILURE(MISSING) MASTER FILE !AND STOP THE SYSTEM. printstring(jtxt.file." lost, major fault. Flag: ") write(flag, 2) newlines(2) stop end ; !OF JJMASTER FAILURE. endoffile