<> <> <> <> <> <> <> DIRECTORY AlpineEnvironment, Basics, AlpineLog, LogBasic, LogInline, LogBasicInternal, LogRep, PrincOpsUtils; LogBasicTailImpl: MONITOR IMPORTS Basics, AlpineLog, LogInline, LogBasicInternal, PrincOpsUtils EXPORTS LogBasic = BEGIN PageNumber: TYPE = AlpineEnvironment.PageNumber; RecordID: TYPE = AlpineLog.RecordID; wordsPerPage: CARDINAL = AlpineEnvironment.wordsPerPage; Header: PROC [p: LONG POINTER] RETURNS [LONG POINTER TO LogRep.Header] = INLINE { RETURN [LOOPHOLE[p]] }; CallerProgrammingError: ERROR = CODE; <> <> curPageRecordID: AlpineLog.RecordID; curPageWordsUsed: INT [0 .. wordsPerPage]; curPagePtr: LONG POINTER _ NIL; <> pagesLeft: INT; <> curVersion: LogRep.PageVersion; <> nPagesWritten: INT _ 0; nPartFullPagesWritten: INT _ 0; <> CurrentRecordID: INTERNAL PROC [] RETURNS [RecordID] = INLINE { RETURN [LogInline.AddC[curPageRecordID, curPageWordsUsed]] }; OpenForPut: PUBLIC ENTRY PROC [ nextPage: PageNumber, version: LogRep.PageVersion, nextRecord: RecordID] = { <> IF LogInline.WordInPageFromRecordID[nextRecord] # 0 THEN ERROR CallerProgrammingError; curPageRecordID _ nextRecord; curPageWordsUsed _ 0; curVersion _ version; [pagesLeft, curPagePtr] _ LogBasicInternal.OpenCoreForPut[nextPage, version, nextRecord]; LOOPHOLE[curPagePtr, LONG POINTER TO CARDINAL]^ _ 0; <> }; CloseForPut: PUBLIC ENTRY PROC [] = { LogBasicInternal.CloseCoreForPut[]; curPagePtr _ NIL; }; RecordIDOfNextPut: PUBLIC ENTRY PROC [] RETURNS [RecordID] = { RETURN [CurrentRecordID[]] }; Put: PUBLIC --EXTERNAL-- PROC [ from: AlpineLog.Block, force: BOOL, writeID: BOOL] RETURNS [thisRecord, followingRecord: RecordID] = { <> totalLen: INT _ 0; FOR b: AlpineLog.BlockPtr _ @from, b.rest UNTIL b = NIL DO len: INT = b.length; IF len > 0 THEN { IF b.base # NIL THEN { offset: INT _ - LOOPHOLE[Basics.BITAND[AlpineEnvironment.wordsPerPage-1, LOOPHOLE[b.base, Basics.LongNumber[pair]].lo], INTEGER]; <> UNTIL offset >= len DO touch: CARDINAL _ LOOPHOLE[b.base + offset, LONG POINTER TO CARDINAL]^; offset _ offset + AlpineEnvironment.wordsPerPage; ENDLOOP; }; totalLen _ totalLen + len; }; ENDLOOP; <> IF totalLen NOT IN [LogBasic.minBlockLen .. LogBasic.maxBlockLen] THEN ERROR CallerProgrammingError; <> <> [thisRecord, followingRecord] _ PutEntry[totalLen, from, force, writeID]; IF force THEN LogBasicInternal.ForceTo[followingRecord: followingRecord]; }; PutEntry: ENTRY PROC [ totalLen: CARDINAL, from: AlpineLog.Block, force: BOOL, writeID: BOOL] RETURNS [thisRecord, followingRecord: RecordID] = { isContinuation: BOOL _ FALSE; <> <> <<(i.e. curPageWordsUsed < wordsPerPage-SIZE[LogRep.Header]), so this record starts on the>> <> thisRecord _ CurrentRecordID[]; IF writeID THEN { <> IF from.length < LogRep.CheckpointCompleteRecord.SIZE - LogRep.StrBody.SIZE THEN RETURN WITH ERROR CallerProgrammingError; LOOPHOLE[from.base, LONG POINTER TO LogRep.CheckpointCompleteRecord].thisRecordID _ thisRecord; }; DO <> wordsThisBlock: CARDINAL _ MIN[(wordsPerPage-SIZE[LogRep.Header])-curPageWordsUsed, totalLen]; wordsThisCopy: CARDINAL; totalLen _ totalLen-wordsThisBlock; --words remaining when this block finished <> <> Header[curPagePtr+curPageWordsUsed]^ _ [ valid: FALSE, version: curVersion, hasContinuation: (totalLen # 0), isContinuation: isContinuation, nWords: wordsThisBlock+SIZE[LogRep.Header]]; curPageWordsUsed _ curPageWordsUsed+SIZE[LogRep.Header]; DO <> wordsThisCopy _ MIN[from.length, wordsThisBlock]; PrincOpsUtils.LongCopy[ to: curPagePtr+curPageWordsUsed, from: from.base, nwords: wordsThisCopy]; curPageWordsUsed _ curPageWordsUsed+wordsThisCopy; IF wordsThisCopy = wordsThisBlock THEN EXIT; < wordsThisCopy = from.length, from.rest # NIL.>> wordsThisBlock _ wordsThisBlock-wordsThisCopy; from _ from.rest^; ENDLOOP; <> IF totalLen # 0 THEN { -- AlpineLog record not all written. <> <> AdvancePage[]; from.base _ from.base+wordsThisCopy; from.length _ from.length-wordsThisCopy; isContinuation _ TRUE; } ELSE { -- AlpineLog record all written. <> <> IF force OR (curPageWordsUsed >= wordsPerPage-SIZE[LogRep.Header]) THEN AdvancePage[]; RETURN [thisRecord, CurrentRecordID[]]; } ENDLOOP; }; Force: PUBLIC PROC [followingRecord: RecordID] = { <> AdvanceTo: ENTRY PROC [followingRecord: RecordID] = { <> <> IF AlpineLog.Compare[followingRecord, curPageRecordID] # greater THEN RETURN; <> IF AlpineLog.Compare[followingRecord, CurrentRecordID[]] = greater THEN RETURN WITH ERROR CallerProgrammingError; AdvancePage[]; }; AdvanceTo[followingRecord]; <> LogBasicInternal.ForceTo[followingRecord]; }; AdvancePage: INTERNAL PROC [] = { <> IF curPageWordsUsed # wordsPerPage THEN { nPartFullPagesWritten _ nPartFullPagesWritten + 1; LOOPHOLE[curPagePtr+curPageWordsUsed, LONG POINTER TO CARDINAL]^ _ 0 }; nPagesWritten _ nPagesWritten + 1; <> Header[curPagePtr].valid _ TRUE; pagesLeft _ pagesLeft - 1; IF pagesLeft = 0 THEN [curVersion, pagesLeft, curPagePtr] _ LogBasicInternal.AdvanceChunk[] <> ELSE curPagePtr _ curPagePtr + AlpineEnvironment.wordsPerPage; <> Header[curPagePtr].valid _ FALSE; curPageRecordID _ LogInline.AddC[curPageRecordID, wordsPerPage]; curPageWordsUsed _ 0; }; END. CHANGE LOG Created by MBrown on June 15, 1982 3:38 pm <> Changed by MBrown on June 22, 1982 11:46 am <> <> Changed by MBrown on August 9, 1982 5:54 pm <> Changed by MBrown on August 12, 1982 4:15 pm <> <> Changed by MBrown on September 10, 1982 10:09 pm <> Changed by MBrown on September 21, 1982 2:40 pm <> Changed by MBrown on October 3, 1982 8:30 pm <> <> Changed by MBrown on October 11, 1982 4:21 pm <> Changed by MBrown on November 10, 1982 3:10 pm <> <> <> <> <> <<>>