<> <> <> <> <<<> <> <> <> <> <> <> <> <> <> <>>> DIRECTORY BasicTime USING [Now], FS USING [Close, Copy, Create, Delete, Error, GetName, maxFNameLength, nullOpenFile, Open, OpenFile], IO USING [STREAM], NSString USING [AppendString, String, StringFromMesaString, StringRep, TruncateString], PrintQueue, PrintingTypes USING [Option], PrincOps USING [bytesPerPage, PageCount, wordsPerPage], PrincOpsUtils USING [PagesForWords], Process USING [Detach], <> PSAsyncMsg USING [ExpandArrayAndPutString], <> QueueFile, Rope USING [FromRefText, ROPE, ToRefText], System USING [nullID, UniversalID], XMessage USING [StringArray] ; PrintQueueImpl: MONITOR IMPORTS BasicTime, FS, NSString, PrincOpsUtils, Process, PSAsyncMsg, Rope EXPORTS PrintQueue, QueueFile = BEGIN <> Error: PUBLIC ERROR [errortype: PrintQueue.Errortype] = CODE; InsufficientPages: PUBLIC ERROR = CODE; -- for QueueFile CreateError: PUBLIC ERROR = CODE; -- for QueueFile LocalError: ERROR = CODE; <> ROPE: TYPE ~ Rope.ROPE; ObjectStatus: TYPE = MACHINE DEPENDENT{pending(0), current(1), complete(2), scavanged(3), unlinked(4), null(maxObjectStatus)}; QueueElement: TYPE = RECORD [ qObject: PrintQueue.QueueObjectHandle _, previous, next: CARDINAL _, <> stage: PrintQueue.QueueStage _, status: ObjectStatus _, testPattern: BOOLEAN _ FALSE]; NotifyProcs: TYPE = ARRAY PrintQueue.QueueStage OF PrintQueue.NewObjectQueuedProc; Queue: TYPE = ARRAY [0..builtInFixedQueueSize) OF QueueElement; QueueObjectPointer: TYPE = REF QueueObjectArray; QueueObjectArray: TYPE = ARRAY [0..builtInFixedQueueSize) OF PrintQueue.QueueObject; DataRecord: TYPE = RECORD [queue: Queue, qStats: PrintQueue.StatsRecord]; <> builtInFixedQueueSize: CARDINAL = 40; maxObjectStatus: CARDINAL = 7; maxStringBytes: CARDINAL = PrintQueue.maxStringBytes; nullQueueIndex: CARDINAL = LAST[CARDINAL]; blank: CHAR = ' ; dataSpacePages: PrincOps.PageCount = PrincOpsUtils.PagesForWords[ SIZE[DataRecord] + SIZE[QueueObjectArray] + 1]; <> <> <> printingOption: PrintingTypes.Option _ unknown; initialized: BOOLEAN _ FALSE; -- for safety qFiletrace: QueueFile.TraceLevel _ none; queueObjects: QueueObjectPointer; -- can be declared in Initialize's local frame notifyProc: NotifyProcs _ ALL[NIL]; <> dataRecord: REF DataRecord _ NIL; spoolDirectory: ROPE _ NIL; -- Is opened/created in the Initialize. <> <<==== ==== ==== ==== ==== ====>> <> <<==== ==== ==== ==== ==== ====>> Requeue: PUBLIC ENTRY PROCEDURE [ qOH: PrintQueue.QueueObjectHandle _ PrintQueue.nilQueueObjectHandle, fromQueue: PrintQueue.QueueStage, toQueue: PrintQueue.QueueStage, position: PrintQueue.RelativePosition _ back] RETURNS [returnQOH: PrintQueue.QueueObjectHandle] = BEGIN ENABLE UNWIND => NULL; <> <> qIndex: CARDINAL _ IF qOH # PrintQueue.nilQueueObjectHandle THEN FindIndex[qOH] ELSE FindFirst[fromQueue]; SELECT TRUE FROM qIndex = nullQueueIndex => RETURN [PrintQueue.nilQueueObjectHandle]; fromQueue = inactive => MakeNull[qIndex]; fromQueue = tpInactive => MakeTPNull[qIndex]; toQueue = inactive => BEGIN IF dataRecord.queue[qIndex].testPattern THEN toQueue _ tpInactive; DeleteFile[dataRecord.queue[qIndex].qObject]; --This used to be done only if qObject wasn't a test pattern; now done for all because test pattern interleaved files need to be deleted for feps9700 and DeleteFile will not succeed in deleting a test pattern interpress file. END; ENDCASE => NULL; returnQOH _ SELECT TRUE FROM qOH # PrintQueue.nilQueueObjectHandle AND dataRecord.queue[qIndex].next # nullQueueIndex => dataRecord.queue[dataRecord.queue[qIndex].next].qObject, --return next qOH # PrintQueue.nilQueueObjectHandle => PrintQueue.nilQueueObjectHandle, <> ENDCASE => dataRecord.queue[qIndex].qObject; -- return first one IF fromQueue # toQueue THEN BEGIN Unlink[qIndex]; IF position = back THEN AddLast[qIndex, toQueue] ELSE AddFirst[qIndex, toQueue]; END; <> InternalBackup[]; --Backup the print queue to the backing file. TellClient[toQueue]; END; -- Requeue Next: PUBLIC ENTRY PROCEDURE [ qOH: PrintQueue.QueueObjectHandle _ PrintQueue.nilQueueObjectHandle, fromQueue: PrintQueue.QueueStage] RETURNS [PrintQueue.QueueObjectHandle] = BEGIN ENABLE UNWIND => NULL; <> <> <> <> qIndex: CARDINAL _ IF qOH # PrintQueue.nilQueueObjectHandle THEN FindIndex[qOH] ELSE FindFirst[fromQueue]; RETURN[SELECT TRUE FROM qIndex = nullQueueIndex AND qOH = PrintQueue.nilQueueObjectHandle --queue must be empty => PrintQueue.nilQueueObjectHandle, qIndex # nullQueueIndex AND qOH = PrintQueue.nilQueueObjectHandle --return first entry => dataRecord.queue[qIndex].qObject, qIndex # nullQueueIndex AND dataRecord.queue[qIndex].next # nullQueueIndex <> => dataRecord.queue[dataRecord.queue[qIndex].next].qObject, ENDCASE => PrintQueue.nilQueueObjectHandle]; --no more in queue END; -- Next Previous: PUBLIC ENTRY PROCEDURE [ qOH: PrintQueue.QueueObjectHandle _ PrintQueue.nilQueueObjectHandle, fromQueue: PrintQueue.QueueStage] RETURNS [PrintQueue.QueueObjectHandle] = BEGIN ENABLE UNWIND => NULL; <> <> <> <> qIndex: CARDINAL _ IF qOH # PrintQueue.nilQueueObjectHandle THEN FindIndex[qOH] ELSE FindLast[fromQueue]; RETURN[SELECT TRUE FROM qIndex = nullQueueIndex AND qOH = PrintQueue.nilQueueObjectHandle --queue must be empty => PrintQueue.nilQueueObjectHandle, qIndex # nullQueueIndex AND qOH = PrintQueue.nilQueueObjectHandle --return last entry => dataRecord.queue[qIndex].qObject, qIndex # nullQueueIndex AND dataRecord.queue[qIndex].previous # nullQueueIndex <> => dataRecord.queue[dataRecord.queue[qIndex].previous].qObject, ENDCASE => PrintQueue.nilQueueObjectHandle]; --no more in queue END; -- Previous Empty: PUBLIC ENTRY PROCEDURE [queue: PrintQueue.QueueStage] RETURNS [BOOLEAN] = BEGIN ENABLE UNWIND => NULL; RETURN[FindFirst[queue] = nullQueueIndex]; END; -- Empty ReserveForTestPattern: PUBLIC ENTRY PROCEDURE [ qOH: PrintQueue.QueueObjectHandle _ PrintQueue.nilQueueObjectHandle, fromQueue: PrintQueue.QueueStage _ inactive, toQueue: PrintQueue.QueueStage _ tpInactive] RETURNS [PrintQueue.QueueObjectHandle] = BEGIN ENABLE UNWIND => NULL; qIndex: CARDINAL _ IF qOH # PrintQueue.nilQueueObjectHandle THEN FindIndex[qOH] ELSE FindFirst[fromQueue]; SELECT TRUE FROM qIndex = nullQueueIndex => RETURN[PrintQueue.nilQueueObjectHandle]; fromQueue = inactive => MakeNull[qIndex]; ENDCASE => NULL; dataRecord.queue[qIndex].testPattern _ TRUE; Unlink[qIndex]; AddLast[qIndex, toQueue]; InternalBackup[]; <> TellClient[toQueue]; RETURN[dataRecord.queue[qIndex].qObject]; END; -- ReserveForTestPattern ReleaseAsTestPattern: PUBLIC ENTRY PROCEDURE [qOH: PrintQueue.QueueObjectHandle, fromQueue: PrintQueue.QueueStage _ tpInactive, toQueue: PrintQueue.QueueStage _ inactive] = BEGIN ENABLE UNWIND => NULL; qIndex: CARDINAL _ IF qOH # PrintQueue.nilQueueObjectHandle THEN FindIndex[qOH] ELSE FindFirst[fromQueue]; dataRecord.queue[qIndex].testPattern _ FALSE; DeleteFile[dataRecord.queue[qIndex].qObject]; MakeNull[qIndex]; Unlink[qIndex]; AddLast[qIndex, toQueue]; InternalBackup[]; <> TellClient[toQueue]; END; -- ReleaseAsTestPattern QueueWatcher: PUBLIC ENTRY PROCEDURE [ proc: PrintQueue.NewObjectQueuedProc, queueStage: PrintQueue.QueueStage] = BEGIN ENABLE UNWIND => NULL; IF proc # NIL AND notifyProc[queueStage] # NIL THEN Error[multipleWatchers]; notifyProc[queueStage] _ proc; IF FindFirst[queueStage] # nullQueueIndex THEN TellClient[queueStage]; END; -- QueueWatcher LocateHandle: PUBLIC ENTRY PROCEDURE [fileSent: System.UniversalID] RETURNS [qOH: PrintQueue.QueueObjectHandle _ PrintQueue.nilQueueObjectHandle, queueStage: PrintQueue.QueueStage _ inactive] = BEGIN ENABLE UNWIND => NULL; FOR qIndex: CARDINAL IN [0..builtInFixedQueueSize) DO IF dataRecord.queue[qIndex].qObject.uid = fileSent THEN RETURN[dataRecord.queue[qIndex].qObject, dataRecord.queue[qIndex].stage]; ENDLOOP; END; -- LocateHandle WhereIs: PUBLIC ENTRY PROCEDURE [qOH: PrintQueue.QueueObjectHandle] RETURNS [valid: BOOLEAN, queueStage: PrintQueue.QueueStage] = BEGIN ENABLE UNWIND => NULL; FOR qIndex: CARDINAL IN [0..builtInFixedQueueSize) DO IF dataRecord.queue[qIndex].qObject = qOH THEN RETURN[TRUE, dataRecord.queue[qIndex].stage]; ENDLOOP; RETURN[FALSE, temp --qOH not actually found--]; END; -- WhereIs CopyStringIn: PUBLIC ENTRY PROCEDURE [qOH: PrintQueue.QueueObjectHandle, fromString: NSString.String, toField: PrintQueue.ObjectStringField] = BEGIN -- Copies fromString to qOH.toField ENABLE UNWIND => NULL; truncatedString: NSString.String; toString: NSString.String; IF qOH = PrintQueue.nilQueueObjectHandle THEN Error[nullQueueObject]; toString _ SELECT toField FROM fileName => qOH.fileName, localFileName => qOH.localFileName, sender => qOH.sender, recipient => qOH.recipient, operatorMsg => qOH.operatorMsg, ENDCASE --errorMsg-- => qOH.errorMsg; truncatedString _ NSString.TruncateString[fromString, IF fromString.length < toString.maxLength THEN fromString.length ELSE toString.maxLength]; toString.length _ 0; toString _ NSString.AppendString[toString, truncatedString]; END; -- CopyStringIn GetQueueObject: PUBLIC ENTRY PROCEDURE [] RETURNS [qOH: PrintQueue.QueueObjectHandle] = BEGIN <> ENABLE UNWIND => NULL; qOH _ NEW[PrintQueue.QueueObject.fax495]; END; -- of GetQueueObject CopyQueueObject: PUBLIC ENTRY PROCEDURE [ fromQOH: PrintQueue.QueueObjectHandle, toQOH: PrintQueue.QueueObjectHandle] = TRUSTED BEGIN ENABLE UNWIND => NULL; Copy: PROC [p: PACKED ARRAY PrintQueue.StringBody OF CHAR] RETURNS [s: NSString.String] = TRUSTED BEGIN s _ NEW[NSString.StringRep[LAST[PrintQueue.StringBody]+1]]; FOR i: PrintQueue.StringBody IN PrintQueue.StringBody DO s[i] _ p[i]; ENDLOOP; END; CopyPhone: PROC [p: PACKED ARRAY [0..PrintQueue.maxPhoneNoLength) OF CHAR] RETURNS [s: NSString.String] = TRUSTED BEGIN s _ NEW[NSString.StringRep[PrintQueue.maxPhoneNoLength]]; FOR i: [0..PrintQueue.maxPhoneNoLength) IN [0..PrintQueue.maxPhoneNoLength) DO s[i] _ p[i]; ENDLOOP; END; Copy4: PROC [p: PACKED ARRAY [0..4) OF CHAR] RETURNS [s: NSString.String] = TRUSTED BEGIN s _ NEW[NSString.StringRep[4]]; FOR i: [0..4) IN [0..4) DO s[i] _ p[i]; ENDLOOP; END; toQOH^ _ fromQOH^; <> toQOH.fileName _ Copy[toQOH.fileNameBody]; toQOH.localFileName _ Copy[toQOH.localFileNameBody]; toQOH.sender _ Copy[toQOH.senderBody]; toQOH.recipient _ Copy[toQOH.recipientBody]; toQOH.operatorMsg _ Copy[toQOH.operatorMsgBody]; toQOH.errorMsg _ Copy[toQOH.errorMsgBody]; WITH q: toQOH SELECT FROM fax495 => FOR i: CARDINAL IN [0..PrintQueue.maxFaxPhoneNos) DO q.transmitData[i].phoneNumber _ CopyPhone[q.transmitData[i].phoneNumberBody]; q.transmitData[i].errorCode _ Copy4[q.transmitData[i].errorCodeBody]; ENDLOOP; ENDCASE; END; --CopyQueueObject Stats: PUBLIC ENTRY PROCEDURE RETURNS [stats: PrintQueue.StatsRecord] = BEGIN ENABLE UNWIND => NULL; RETURN[dataRecord.qStats]; END; -- Stats ResetStats: PUBLIC ENTRY PROCEDURE = BEGIN dataRecord.qStats _ [statsFrom: BasicTime.Now[], inconsistantAtInit: 0, activity: ALL[0]]; END; -- ResetStats Backup: PUBLIC ENTRY PROCEDURE = BEGIN <> InternalBackup[]; <> END; --Backup <<==== ==== ==== ==== ==== ====>> <> <<==== ==== ==== ==== ==== ====>> CreateTempFile: PUBLIC ENTRY PROCEDURE [fName: NSString.String, fBytes: LONG CARDINAL] RETURNS [fileID: FS.OpenFile, fileH: IO.STREAM] = BEGIN ENABLE UNWIND => NULL; trucatedString: NSString.String; <> <> <<=====================================>> CreateFile: PROC = BEGIN <<=====================================>> <> <<[type[tSpool]], [name[trucatedString]], [dataSize[fBytes]]];>> fileID _ FS.Create[name: Rope.FromRefText[trucatedString], pages: (fBytes/PrincOps.bytesPerPage)+1]; END; -- CreateFile <<=====================================>> trucatedString _ NSString.TruncateString[fName, FS.maxFNameLength]; fileID _ FS.nullOpenFile; CreateFile[ ! FS.Error => BEGIN IF qFiletrace # none THEN BEGIN nsCreateFileError: NSString.String = " **CreateFile: <1> !<2>"; stringArray: REF XMessage.StringArray _ NEW[XMessage.StringArray[2]]; stringArray.data[0] _ trucatedString; stringArray.data[1] _ Rope.ToRefText[error.explanation]; PSAsyncMsg.ExpandArrayAndPutString[nsCreateFileError, stringArray]; END; IF error.code = $volumeFull THEN ERROR InsufficientPages ELSE ERROR CreateError; END; ]; <> <> < BEGIN>> <> <; <2>"L];>> <> <> <<[stringArray[1],] _ MsgOps.FilingErrToMsg[error];>> <> <> <> <> <<];>> <<>> <> <> < BEGIN>> <> < CONTINUE];>> <> <> END; -- CreateTempFile Delete: PUBLIC ENTRY PROCEDURE [fileID: FS.OpenFile, file: IO.STREAM _ NIL] RETURNS [FS.OpenFile] = BEGIN ENABLE UNWIND => NULL; IF fileID # FS.nullOpenFile THEN FS.Close[fileID ! FS.Error => CONTINUE]; --cause FileDelete Opens it again. FileDelete[fileID ! LocalError => CONTINUE]; RETURN [FS.nullOpenFile]; END; -- Delete MakePermanent: PUBLIC PROCEDURE [file: FS.OpenFile, attrs: NSString.String] = BEGIN <> [] _ FS.Copy[from: FS.GetName[file].fullFName, to: Rope.FromRefText[attrs], wDir: spoolDirectory] END; -- MakePermanent. SetTrace: PUBLIC PROCEDURE [trace: QueueFile.TraceLevel] = {qFiletrace _ trace}; <<==== ==== ==== ==== ==== ==== >> <> <<==== ==== ==== ==== ==== ====>> InternalBackup: INTERNAL PROCEDURE [] = BEGIN <> END; FindIndex: INTERNAL PROCEDURE [qOH: PrintQueue.QueueObjectHandle] RETURNS [qIndex: CARDINAL] = BEGIN FOR qIndex IN [0..builtInFixedQueueSize) DO IF dataRecord.queue[qIndex].qObject = qOH THEN RETURN[qIndex]; ENDLOOP; ERROR Error[invalidQueueObject]; END; -- FindIndex MakeNull: INTERNAL PROCEDURE [qIndex: CARDINAL] = BEGIN Copy: PROC [p: PACKED ARRAY PrintQueue.StringBody OF CHAR] RETURNS [s: NSString.String] = BEGIN s _ NEW[NSString.StringRep[LAST[PrintQueue.StringBody]+1]]; FOR i: PrintQueue.StringBody IN PrintQueue.StringBody DO s[i] _ p[i]; ENDLOOP; END; qOH: PrintQueue.QueueObjectHandle _ dataRecord.queue[qIndex].qObject; IF dataRecord.queue[qIndex].status # null THEN BEGIN qOH^ _ [ fileName: NEW[NSString.StringRep[maxStringBytes]], localFileName: NEW[NSString.StringRep[maxStringBytes]], sender: NEW[NSString.StringRep[maxStringBytes]], recipient: NEW[NSString.StringRep[maxStringBytes]], operatorMsg: NEW[NSString.StringRep[maxStringBytes]], errorMsg: NEW[NSString.StringRep[maxStringBytes]], optionVariant: unknown[] --Compiler won't accept select stmt (below) here. **AJ 12/20/83 ]; dataRecord.queue[qIndex].status _ null; END; IF qOH.option # printingOption THEN BEGIN --Change printing option if necessary. SELECT printingOption FROM bansheeDl => qOH.optionVariant _ bansheeDl[]; d1 => qOH.optionVariant _ d1[]; fax295 => qOH.optionVariant _ fax295[]; fax495 => qOH.optionVariant _ fax495[]; feps9700 => qOH.optionVariant _ feps9700[]; fx3500 => qOH.optionVariant _ fx3500[]; raven => qOH.optionVariant _ raven[]; ENDCASE => ERROR; WITH q: qOH SELECT FROM fax495 => FOR i: CARDINAL IN [0..PrintQueue.maxFaxPhoneNos) DO q.transmitData[i].phoneNumber _ NEW[NSString.StringRep[PrintQueue.maxPhoneNoLength]]; q.transmitData[i].errorCode _ NEW[NSString.StringRep[4]]; ENDLOOP; ENDCASE; END; END; -- MakeNull MakeTPNull: INTERNAL PROCEDURE [qIndex: CARDINAL] = BEGIN -- assumes STRINGs are still pointing at correct bodies qOH: PrintQueue.QueueObjectHandle _ dataRecord.queue[qIndex].qObject; IF dataRecord.queue[qIndex].status # null THEN BEGIN qOH.fileID _ FS.nullOpenFile; qOH.uid _ System.nullID; qOH.numberCopies _ qOH.platesDecomposed _ 0; qOH.firstPageToPrint _ 1; qOH.lastPageToPrint _ LAST[CARDINAL]; qOH.twoSided _ qOH.staple _ FALSE; qOH.printObjectHandle _ PrintQueue.nilPrintObjectHandle; qOH.currentStatus _ qOH.priorStatus _ null; qOH.bannerOnly _ FALSE; qOH.sender.length _ qOH.recipient.length _ qOH.operatorMsg.length _ qOH.errorMsg.length _ 0; dataRecord.queue[qIndex].status _ null; END; SELECT printingOption FROM --Even if queue object was already null, must initialize it to current printing option. bansheeDl => qOH.optionVariant _ bansheeDl[]; d1 => qOH.optionVariant _ d1[]; fax295 => qOH.optionVariant _ fax295[]; fax495 => qOH.optionVariant _ fax495[]; feps9700 => qOH.optionVariant _ feps9700[]; fx3500 => qOH.optionVariant _ fx3500[]; raven => qOH.optionVariant _ raven[]; ENDCASE => ERROR; WITH q: qOH SELECT FROM fax495 => FOR i: CARDINAL IN [0..PrintQueue.maxFaxPhoneNos) DO q.transmitData[i].phoneNumber _ NEW[NSString.StringRep[PrintQueue.maxPhoneNoLength]]; q.transmitData[i].errorCode _ NEW[NSString.StringRep[4]]; ENDLOOP; ENDCASE; END; -- MakeTPNull DeleteFile: INTERNAL PROCEDURE [qOH: PrintQueue.QueueObjectHandle] = BEGIN IF qOH.deleteInactiveFile AND qOH.fileID # FS.nullOpenFile THEN FileDelete[qOH.fileID ! LocalError => CONTINUE]; qOH.localFileName.length _ 0; qOH.fileID _ FS.nullOpenFile; WITH q: qOH SELECT FROM feps9700 => BEGIN --delete interleaved IP master, if any IF q.ivFileID # FS.nullOpenFile THEN FileDelete[q.ivFileID ! LocalError => CONTINUE]; q.ivFileID _ FS.nullOpenFile; END; ENDCASE; END; -- DeleteFile FileDelete: INTERNAL PROCEDURE [fileID: FS.OpenFile] = BEGIN file: FS.OpenFile; <> fileError: BOOLEAN _ FALSE; name: ROPE _ FS.GetName[fileID].fullFName; FS.Close[fileID]; FS.Delete[name: name] <> <> <> < BEGIN>> <> <"L];>> <> <<[stringArray[0],] _ MsgOps.FilingErrToMsg[error];>> <> <> <> <> <<>> <> < BEGIN>> <> <"L];>> <> <<[stringArray[0],] _ MsgOps.FilingErrToMsg[error];>> <> <> <> <> <<>> < LocalError;>> END; -- FileDelete Unlink: INTERNAL PROCEDURE [qIndex: CARDINAL] = BEGIN OPEN dataRecord; IF queue[qIndex].next # nullQueueIndex THEN queue[queue[qIndex].next].previous _ queue[qIndex].previous; IF queue[qIndex].previous # nullQueueIndex THEN queue[queue[qIndex].previous].next _ queue[qIndex].next; queue[qIndex].previous _ queue[qIndex].next _ nullQueueIndex; queue[qIndex].status _ unlinked; END; -- Unlink AddLast: INTERNAL PROCEDURE [qIndex: CARDINAL, qStage: PrintQueue.QueueStage, objStatus: ObjectStatus _ pending] = BEGIN OPEN dataRecord; -- assumes queue[qIndex] has been Unlinked. IF queue[qIndex].status # unlinked THEN ERROR; -- removable for production queue[qIndex].previous _ FindLast[qStage]; IF queue[qIndex].previous # nullQueueIndex THEN queue[queue[qIndex].previous].next _ qIndex; queue[qIndex].stage _ qStage; queue[qIndex].status _ objStatus; <> qStats.activity[qStage] _ qStats.activity[qStage] + 1; END; -- AddLast AddFirst: INTERNAL PROCEDURE [qIndex: CARDINAL, qStage: PrintQueue.QueueStage, objStatus: ObjectStatus _ pending] = BEGIN OPEN dataRecord; -- assumes queue[qIndex] has been Unlinked. IF queue[qIndex].status # unlinked THEN ERROR; -- removable for production queue[qIndex].next _ FindFirst[qStage]; IF queue[qIndex].next # nullQueueIndex THEN queue[queue[qIndex].next].previous _ qIndex; queue[qIndex].stage _ qStage; queue[qIndex].status _ objStatus; <> qStats.activity[qStage] _ qStats.activity[qStage] + 1; END; -- AddFirst FindLast: INTERNAL PROCEDURE [qStage: PrintQueue.QueueStage] RETURNS [qIndex: CARDINAL] = BEGIN OPEN dataRecord; -- returns qIndex of last (latest) entry in queue or nullQueueIndex FOR qIndex IN [0..builtInFixedQueueSize) DO IF queue[qIndex].stage = qStage THEN BEGIN UNTIL queue[qIndex].next = nullQueueIndex DO qIndex _ queue[qIndex].next; ENDLOOP; RETURN[qIndex]; END; ENDLOOP; RETURN[nullQueueIndex]; END; -- FindLast FindFirst: INTERNAL PROCEDURE [qStage: PrintQueue.QueueStage] RETURNS [qIndex: CARDINAL] = BEGIN OPEN dataRecord; -- returns qIndex of first (earliest) entry in queue or nullQueueIndex FOR qIndex IN [0..builtInFixedQueueSize) DO IF queue[qIndex].stage = qStage THEN BEGIN UNTIL queue[qIndex].previous = nullQueueIndex DO qIndex _ queue[qIndex].previous; ENDLOOP; RETURN[qIndex]; END; ENDLOOP; RETURN[nullQueueIndex]; END; -- FindFirst TellClient: INTERNAL PROCEDURE [q: PrintQueue.QueueStage] = TRUSTED BEGIN IF notifyProc[q] # NIL THEN Process.Detach[FORK notifyProc[q]]; END; <<==== ==== ==== ====>> <> <<==== ==== ==== ====>> Initialize: PUBLIC PROCEDURE [directory: REF TEXT, queueEntries: CARDINAL, currentOption: PrintingTypes.Option] RETURNS [queueSize: CARDINAL] = BEGIN nsQueueBackingStore: ROPE = "PrintQueue14.BackingStore"; oldnsQueueBackingStore: ROPE = "PrintQueue10.BackingStore"; file: FS.OpenFile _ FS.nullOpenFile; newBackingFile: BOOLEAN _ FALSE; <<====================================================>> CreateBackingFile: PROC[] = BEGIN <<====================================================>> <> <<[type[backingStoreFileType]], [dataSize[dataSpaceBytes]],>> <<[name[nsQueueBackingStore]]];>> file _ FS.Create[name: nsQueueBackingStore, wDir: Rope.FromRefText[directory], pages: dataSpacePages]; END; -- CreateBackingFile <<====================================================>> InitializeSpace: PROC = BEGIN OPEN dataRecord; <<====================================================>> FOR i: CARDINAL IN [0..builtInFixedQueueSize) DO -- Allocate the QueueObjects <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<];>> <