-- Transactions>TransactionLogImpl.mesa (last edited by Gobbel on December 31, 1980 4:37 PM)
DIRECTORY
File USING [Capability, ID, nullID, PageNumber],
Inline USING [LongMult],
PilotFileTypes USING [tTransactionLog],
SimpleSpace USING [CopyIn, Create, Handle, Kill, LongPointer, Map, Unmap],
Space USING [PageCount],
Transaction USING [],
TransactionInternal USING [Checksum, countLogEntry, disabled, FilePageCount, FilePageNumber, Handle, LogFileEntry, LogFileEntryData, logFileFormatVersion, permissions, ShortenPageCount, ShortenPageNumber, state, TxDescPtr, TxDescriptor, UpdateStateFile, ValidTxIndex],
TransactionState USING [FileOps, LogEntryPtr],
Utilities USING [LongPointerFromPage];
TransactionLogImpl: PROGRAM -- not a MONITOR. The procedures in this module are only called from inside the monitor of TransactionStateImpl.
IMPORTS Inline, SimpleSpace, TransactionInternal, Utilities
EXPORTS TransactionInternal
SHARES File --USING[Capability]-- =
BEGIN OPEN TransactionInternal;
bufferSpace: SimpleSpace.Handle;
countBuffer: Space.PageCount = 40;
BugType: TYPE = {illegalLogOperation, logForInactiveTransaction};
Bug: PRIVATE --PROGRAMMING-- ERROR [BugType] = CODE;
-- Initialization
InitializeLogsA: PUBLIC PROCEDURE =
-- Called once at system startup - create simple spaces for later use.
BEGIN
IF disabled THEN RETURN;
bufferSpace ← SimpleSpace.Create[countBuffer, hyperspace];
END;
InitializeLogsB: PUBLIC PROCEDURE [] =
BEGIN -- may be something here someday-- END;
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
AssureLogRoom: PROCEDURE [pTrans: LONG POINTER TO active TxDescriptor, countOp: FilePageCount, fileOps: TransactionState.FileOps] =
-- Assures that there is enough room in the log file for this transaction to hold countOp additional pages.
-- If no log file is allocated yet, allocates a log file for transaction. Uses a preallocated log file if one available, else creates one.
-- May raise Volume.InsufficientSpace.
BEGIN
countGrowExtra: FilePageCount = 10; -- add this much extra when we have to grow a log file.
trUnused: TxDescPtr;
IF ~pTrans.fileInUse THEN -- allocate a log file..
BEGIN
FOR txUnused: ValidTxIndex IN ValidTxIndex DO -- look for an unused, preallocated file..
trUnused ← @state[txUnused];
IF ~trUnused.fileInUse AND trUnused.logFile ~= File.nullID THEN -- found a preallocated file. Swap file info into current transaction.
{ tempID: File.ID; tempPage: FilePageNumber;
tempID ← pTrans.logFile; tempPage ← pTrans.logFileSize;
pTrans.logFile ← trUnused.logFile;
pTrans.logFileSize ← trUnused.logFileSize;
trUnused.logFile ← tempID; trUnused.logFileSize ← tempPage;
TransactionInternal.UpdateStateFile[];
EXIT };
REPEAT FINISHED => -- have to create a file..
{ pTrans.logFile ← fileOps.CreateFile[ (pTrans.logFileSize ← countOp+countGrowExtra), PilotFileTypes.tTransactionLog]; -- may raise Volume.InsufficientSpace.
TransactionInternal.UpdateStateFile[];
fileOps.MakeFilePermanent[pTrans.logFile] }; -- (now that we’ve remembered its ID)
ENDLOOP;
pTrans.fileInUse ← TRUE;
pTrans.pageFree ← FIRST[FilePageNumber];
pTrans.countPrevLogEntry ← 0;
END;
-- grow the log file as necessary..
IF pTrans.pageFree+countOp>pTrans.logFileSize THEN -- grow the log file..
{ tempSize: FilePageCount = countOp + pTrans.pageFree + countGrowExtra; -- that needed + extra.
fileOps.SetFileSize[pTrans.logFile, tempSize]; -- may raise Volume.InsufficientSpace.
pTrans.logFileSize ← tempSize }; -- now that we have sufficient space.
END;
LogInternal: PUBLIC PROCEDURE [txi: ValidTxIndex, op: TransactionState.LogEntryPtr, fileOps: TransactionState.FileOps] =
-- May raise Volume.InsufficientSpace.
BEGIN
entryData: LONG POINTER TO LogFileEntryData;
pTrans: TxDescPtr = @state[txi];
countOp: FilePageCount = -- total number of pages to log for this operation.
countLogEntry + ( WITH oper: op SELECT FROM
setContents => ShortenPageCount[oper.size],
ENDCASE => 0 );
WITH trans: pTrans SELECT FROM
active =>
BEGIN
AssureLogRoom[@trans, countOp, fileOps]; -- may raise Volume.InsufficientSpace.
WITH oper: op SELECT FROM
setContents =>
-- First log the data, then go back and log the operation info. That way, if the operation info is in the log file, we know that the following data is also in the log file.
BEGIN
count: FilePageCount;
baseLog: File.PageNumber ← trans.pageFree + countLogEntry; -- (skip over header page)
baseData: FilePageNumber ← ShortenPageNumber[oper.base];
countRemaining: FilePageCount ← ShortenPageCount[oper.size];
IF countRemaining>0 --UNTIL count exhausted-- THEN DO
count ← MIN[countBuffer, countRemaining];
SimpleSpace.Map[handle: bufferSpace, window: [ [trans.logFile, permissions], baseLog], andPin: FALSE, countMapped: count];
SimpleSpace.CopyIn[handle: bufferSpace, window: [ [oper.id, permissions], baseData], countMapped: count];
SimpleSpace.Unmap[bufferSpace];
baseLog ← baseLog+countBuffer;
baseData ← baseData+countBuffer;
IF countRemaining<countBuffer THEN EXIT;
countRemaining ← countRemaining-countBuffer;
ENDLOOP;
END;
create, delete, move, makeMutable, makeTemporary, shrink => NULL;
ENDCASE => ERROR Bug[illegalLogOperation];
-- Log the operation info:
SimpleSpace.Map[handle: bufferSpace, window: [ [trans.logFile, permissions], trans.pageFree], andPin: FALSE, countMapped: countLogEntry];
SimpleSpace.Kill[bufferSpace];
entryData ← LOOPHOLE[ SimpleSpace.LongPointer[bufferSpace] ];
BEGIN OPEN e: entryData.logFileEntry;
e.seal ← logFileFormatVersion;
e.transactionHandle ← e.transactionHandle2 ← Handle[trans.txEdition, txi];
e.countPrevEntry ← trans.countPrevLogEntry;
e.op ← op↑;
END;
entryData.checksumData ← Checksum[0, SIZE[LogFileEntry], @entryData.logFileEntry];
SimpleSpace.Unmap[bufferSpace];
trans.pageFree ← trans.pageFree + countOp;
trans.countPrevLogEntry ← countOp; -- remember count of this entry for next time.
END;
ENDCASE => ERROR Bug[logForInactiveTransaction];
END;
END.
LOG
June 2, 1980 2:05 PMGobbelCreated file.
July 21, 1980 2:23 PMMcJonesConverted to new UNCOUNTED ZONE representation.
July 22, 1980 2:59 PMGobbelNow to make it work....
August 27, 1980 1:04 PMKnutsenMerged Log Table into State Table. Major cleanup.
December 31, 1980 4:37 PMGobbelChange capabilities in log file entries to IDs.