-- LogBasic.mesa -- The LogBasic interface is lower-level than the Log interface. The Log interface "knows" --about transactions, while LogBasic does not. The LogBasic interface therefore allows --logging an event that is not associated with a single transaction (e.g. a log checkpoint). -- Last edited by -- MBrown on June 27, 1983 10:04 am DIRECTORY AlpineEnvironment, Log, LogRep; LogBasic: DEFINITIONS = BEGIN VolumeID: TYPE = AlpineEnvironment.VolumeID; FileID: TYPE = AlpineEnvironment.FileID; PageNumber: TYPE = AlpineEnvironment.PageNumber; PageCount: TYPE = AlpineEnvironment.PageNumber; Block: TYPE = Log.Block; RecordID: TYPE = Log.RecordID; WordNumber: TYPE = INT; -- This represents a word index (0-origin) into the online log file. This representation --limits us to a 4 billion byte online log, which may be a problem eventually but --not today. WordCount: TYPE = INT; -- This represents a difference of two WordNumbers, the length of an online log file, --etc. -- Initialization. EstablishLogFile: PROC [logVolume: VolumeID, logFile: FileID]; -- Must be called before any of the procs below. LogFileSize: PROC [] RETURNS [PageCount]; LocateFirstRecord: PROC [] RETURNS [WordNumber]; -- Reads the log file determined by EstablishLogFile. Returns the WordNumber of a --record near the start of the log. -- The intended use of this proc is in recovery from the loss of the restart file. This --proc takes a long time, but is seldom used. -- Sequential reading. -- There is a single stream for reading the log. This stream is used only during recovery. --There is no monitor protection, so the client is responsible for serializing stream calls. -- Sequential reading of the log is more primitive than random access. It knows how to deal --gracefully with the raggedness that defines the end of log. It can be performed even if the --logical addressing structure of the log has not been established (as on the first step of --recovery.) OpenRecordStreamFromWord: PROC [firstWord: WordNumber] RETURNS [notStartOfRecord: BOOL, currentRecord: RecordID]; -- ! InvalidPage -- Creates a stream using physical log addressing. RecordIDs returned by Advance will be --based on the assumption that the RecordID of record found at firstWord is firstWord. OpenRecordStreamFromCheckpoint: PROC [ checkpointWord: WordNumber, checkpointRecord, firstRecord: RecordID] RETURNS [notStartOfRecord: BOOL, currentRecord: RecordID]; -- ! InvalidPage -- Creates a stream using logical log addressing. The logical-physical correspondence is --defined by checkpointWord and checkpointRecord. firstRecord must be less --than checkpointRecord. InvalidPage: ERROR; -- OpenRecordStreamFromXXX was pointed to a page with random garbage in it. -- After this error, the caller should CloseRecordStream[] immediately. CheckCurrentRecord: PROC [] RETURNS [truncated: BOOL]; -- ! Log.Error{ invalidRecordID, invalidRecord } -- This proc may be called before calling GetCurrentRecord, in order to detect errors --that would otherwise be raised by the GetCurrentRecord call. GetCurrentRecord: PROC [currentRecord: RecordID, to: Block] RETURNS [status: Log.ReadProcStatus, wordsRead: CARDINAL]; -- This proc has the same type as Get below. -- This call does not change the state of the stream. GetCurrentPageAndVersion: PROC [] RETURNS [PageNumber, LogRep.PageVersion]; -- ! (none) -- A somewhat peculiar operation, provided for purposes of recovery. AdvanceRecordStream: PROC [] RETURNS [endOfLog, truncatedRecord: BOOL, currentRecord: RecordID]; -- ! (none) -- Positions to next log record, returns its ID. -- If endOfLog, then "currentRecord" is past the end of log. -- If truncatedRecord, then the record before "currentRecord" was incomplete. -- There is no guarantee that "currentRecord" exists in its entirety, only that some prefix --exists. CloseRecordStream: PROC []; -- Shuts down the stream. Must be called before opening the stream again. -- Writing. -- There is a single output stream, created by the call to OpenForPut. The stream is --protected by monitors so it is ok for several processes to call Put without other --synchronization. -- (Note that OpenForPut is done implicitly by EraseLogFile.) -- No non-fatal errors are possible in the basic log writing primitives. An attempt to --write when the online log is (nearly) full causes a wait; another process must free some --online log pages. OpenForPut: PROC [nextPage: PageNumber, version: LogRep.PageVersion, nextRecord: RecordID]; -- Sets up the output stream for writing to file page nextPage, naming the first --record that it writes there nextRecord. AssertNormalOperation: PROC []; -- If normalOperation, then perform more stringent checking for log full. Put: PROC [from: Log.Block, force: BOOL ← FALSE, writeID: BOOL ← FALSE] RETURNS [thisRecord, followingRecord: RecordID]; -- ! Log.Error {writeID, totalLen, logFull} -- Caller need not ensure that all pages of "from" are in main store; Put will touch each --page before entering the log tail monitor. -- If writeID and a log record ID won't fit in the first block, Error[writeID]. -- If total lenth of write request is not IN [minBlockLen .. maxBlockLen], Error[totalLen]. -- Error[logFull] is a server crash; it does not release the log tail monitor or log core monitor. minBlockLen: INT = 1; maxBlockLen: INT = LAST[CARDINAL]; WordNumberFromRecordID: PROC [thisRecord: RecordID] RETURNS [WordNumber]; -- ! Log.Error {recordNonexistent, recordNotOnline} (thisRecord is not valid.) -- If thisRecord is represented in the online log, returns its location. -- Intended for use by the proc that writes checkpointComplete records. Force: PROC [followingRecord: RecordID]; -- ! (none) -- Force all records prior to (not including) followingRecord to be recorded --stably in the online log. RecordIDOfNextPut: PROC [] RETURNS [RecordID]; -- ! (none) -- Returns the RecordID that would have been assigned if this call had been a Put. CloseForPut: PROC []; -- ! (none) -- Flushes all log buffers to disk, and returns log writing component to initial state. maxInvalidLogPages: PageCount = 16; -- This many pages past end of log do not have well-defined values. On restart, these --pages need to be reinitialized. -- Purging. Release: PROC [beforeRecord: RecordID]; -- ! Log.Error {recordNonexistent, recordNotOnline} (beforeRecord is not valid to release.) -- The caller certifies that all records prior to (not including) beforeRecord may --be purged from the online log. -- Random reading. -- Intended to be used only for carrying out intentions, not during recovery. Get: PROC [thisRecord: RecordID, to: Log.Block] RETURNS [status: Log.ReadProcStatus, wordsRead: CARDINAL]; -- Extracts all or part of the contents of a log record. wordsRead is the number of --words of log record touched by the Get call (bounded above by the total length --of the block "to"). END. CHANGE LOG Created by MBrown on 2-Dec-81 Changed by MBrown on 16-Dec-81 15:06:20 -- Initialize takes a File.Capability, not the name of a server. Changed by MBrown on 1-Feb-82 15:10:32 -- Define interface that is decoupled from handles defined in other parts of Alpine. --Change from stream to stateless style reading. Use 48 bit log record ids throughout. Changed by MBrown on August 10, 1982 11:26 pm -- Move Put here from LogPrivate; define realistic Get. Changed by MBrown on August 16, 1982 3:29 pm -- Added sequential reading back in, and simplified random reading correspondingly. Changed by MBrown on September 16, 1982 12:42 pm -- Changes to make recovery implementable. Changed by MBrown on September 23, 1982 1:52 pm -- Added WordNumberFromRecordID. Changed by MBrown on June 27, 1983 9:48 am -- Added AssertNormalOperation.