<> <> <> <> <> <> <> <> DIRECTORY AlpineEnvironment USING[FileVersion, PageCount, PageNumber, PageRun], AlpineInternal USING[FileHandle, LeaderPageHandle, LogRecordID, TransHandle], Basics USING[CompareINT], FileMap USING[ClearLogMapHandle, Handle, VerifyLogMapHandle], LogMap USING[CheckOutOption, CallingErrorType, FileDescription, Location, MappedPageRun], LogMapPrivate USING[IntentionObject, Intention], RedBlackTree USING[Compare, Create, Delete, GetKey, Insert, Lookup, LookupLargest, LookupNextLarger, LookupNextSmaller, LookupSmallest, Node, Table], SafeStorage USING[GetSystemZone], TransactionMap USING[IsCommitted]; LogMapImpl: CEDAR MONITOR LOCKS logMapHandle USING logMapHandle: Handle IMPORTS Basics, FileMap, RedBlackTree, SafeStorage, TM: TransactionMap EXPORTS AlpineInternal, LogMap = BEGIN OPEN AE: AlpineEnvironment, AI: AlpineInternal, LM: LogMap, LMP: LogMapPrivate; Handle: TYPE = REF LogMapObject; LogMapObject: PUBLIC TYPE = MONITORED RECORD[ createTrans: AI.TransHandle, deleteTrans: AI.TransHandle, versionUncommitted: AE.FileVersion, versionUncommittedTrans: AI.TransHandle, versionCommitted: AE.FileVersion, sizeUncommitted: AE.PageCount, sizeUncommittedTrans: AI.TransHandle, sizeCommitted: AE.PageCount, highWaterMarkCommitted: AE.PageCount, leaderPage: AI.LeaderPageHandle, leaderPageTrans: AI.TransHandle, intentionsTable: RedBlackTree.Table, leaderPageIntention: LeaderPageIntention, <> rbKeyRef: REF AE.PageNumber ]; LeaderPageIntention: TYPE = RECORD[trans: AI.TransHandle, logRecordID: AI.LogRecordID]; Error: PUBLIC --CALLING-- ERROR [error: LM.CallingErrorType] = CODE; <> ProbableLockingFailure: --CALLING-- ERROR = CODE; Horrible: --CALLING-- ERROR = CODE; DescribeFile: PUBLIC PROCEDURE[file: AI.FileHandle, trans: AI.TransHandle] RETURNS [fileDesc: LM.FileDescription] = BEGIN -- non-fatal errors: none. MonitoredDescribeFile: ENTRY PROCEDURE[logMapHandle: Handle] = INLINE BEGIN -- non-fatal errors: none. fileDesc.registered _ TRUE; fileDesc.created _ trans = logMapHandle.createTrans; fileDesc.deleted _ trans = logMapHandle.deleteTrans; TRUSTED BEGIN fileDesc.exists _ ( ((fileDesc.created) OR (logMapHandle.createTrans = NIL) OR (TM.IsCommitted[logMapHandle.createTrans])) AND NOT ((fileDesc.deleted) OR ((logMapHandle.deleteTrans # NIL) AND (TM.IsCommitted[logMapHandle.deleteTrans])))); END; fileDesc.sizeChanged _ trans = logMapHandle.sizeUncommittedTrans; END; logMapHandle: Handle _ GetOrReportOnLogMapHandle[file, FALSE]; IF logMapHandle # NIL THEN MonitoredDescribeFile[logMapHandle] ELSE fileDesc.registered _ FALSE; END; <> RegisterCreate: PUBLIC PROCEDURE[file: AI.FileHandle, trans: AI.TransHandle] = BEGIN -- non-fatal errors: none. MonitoredRegisterCreate: ENTRY PROCEDURE[logMapHandle: Handle] = INLINE BEGIN -- non-fatal errors: none. IF logMapHandle.createTrans # NIL THEN RETURN WITH ERROR ProbableLockingFailure; logMapHandle.createTrans _ trans; END; logMapHandle: Handle _ GetOrReportOnLogMapHandle[file, TRUE]; MonitoredRegisterCreate[logMapHandle]; END; <> RegisterDelete: PUBLIC PROCEDURE[file: AI.FileHandle, trans: AI.TransHandle] = BEGIN -- non-fatal errors: none. MonitoredRegisterDelete: ENTRY PROCEDURE[logMapHandle: Handle] = INLINE BEGIN -- non-fatal errors: none. IF logMapHandle.deleteTrans # NIL THEN RETURN WITH ERROR ProbableLockingFailure; logMapHandle.deleteTrans _ trans; END; logMapHandle: Handle _ GetOrReportOnLogMapHandle[file, TRUE]; MonitoredRegisterDelete[logMapHandle]; END; <> SetUncommittedVersion: PUBLIC PROCEDURE[file: AI.FileHandle, trans: AI.TransHandle, version: AE.FileVersion] = BEGIN -- non-fatal errors: none. MonitoredSetUncommittedVersion: ENTRY PROCEDURE[logMapHandle: Handle] = INLINE BEGIN -- non-fatal errors: none. IF ((logMapHandle.versionUncommittedTrans = NIL) OR (trans = NIL) OR (trans = logMapHandle.versionUncommittedTrans)) THEN BEGIN logMapHandle.versionUncommittedTrans _ trans; logMapHandle.versionUncommitted _ version; END ELSE RETURN WITH ERROR ProbableLockingFailure; END; logMapHandle: Handle _ GetOrReportOnLogMapHandle[file, TRUE]; MonitoredSetUncommittedVersion[logMapHandle]; END; <> GetUncommittedVersion: PUBLIC PROCEDURE[file: AI.FileHandle, trans: AI.TransHandle] RETURNS[version: AE.FileVersion] = BEGIN -- non-fatal errors: none. MonitoredGetUncommittedVersion: ENTRY PROCEDURE[logMapHandle: Handle] = INLINE BEGIN -- non-fatal errors: none. IF ((trans # logMapHandle.versionUncommittedTrans) AND (logMapHandle.versionUncommittedTrans # NIL)) THEN TRUSTED BEGIN IF TM.IsCommitted[logMapHandle.versionUncommittedTrans] THEN RETURN WITH ERROR ProbableLockingFailure ELSE version _ 0; END ELSE version _ logMapHandle.versionUncommitted; END; logMapHandle: Handle _ GetOrReportOnLogMapHandle[file, FALSE]; IF logMapHandle = NIL THEN RETURN[0]; MonitoredGetUncommittedVersion[logMapHandle]; END; <> SetCommittedVersion: PUBLIC PROCEDURE[file: AI.FileHandle, version: AE.FileVersion] = BEGIN -- non-fatal errors: none. MonitoredSetCommittedVersion: ENTRY PROCEDURE[logMapHandle: Handle] = INLINE BEGIN -- non-fatal errors: none. logMapHandle.versionCommitted _ version; END; logMapHandle: Handle _ GetOrReportOnLogMapHandle[file, TRUE]; MonitoredSetCommittedVersion[logMapHandle]; END; <> GetCommittedVersion: PUBLIC PROCEDURE[file: AI.FileHandle] RETURNS[version: AE.FileVersion] = BEGIN -- non-fatal errors: none. MonitoredGetCommittedVersion: ENTRY PROCEDURE[logMapHandle: Handle] = INLINE BEGIN -- non-fatal errors: none. version _ logMapHandle.versionCommitted; END; logMapHandle: Handle _ GetOrReportOnLogMapHandle[file, FALSE]; IF logMapHandle = NIL THEN RETURN[0]; MonitoredGetCommittedVersion[logMapHandle]; END; <> SetUncommittedSize: PUBLIC PROCEDURE[file: AI.FileHandle, trans: AI.TransHandle, size: AE.PageCount] = BEGIN -- non-fatal errors: none. MonitoredSetUncommittedSize: ENTRY PROCEDURE[logMapHandle: Handle] = INLINE BEGIN -- non-fatal errors: none. IF ((logMapHandle.sizeUncommittedTrans = NIL) OR (trans = NIL) OR (trans = logMapHandle.sizeUncommittedTrans)) THEN BEGIN logMapHandle.sizeUncommittedTrans _ trans; logMapHandle.sizeUncommitted _ size; END ELSE RETURN WITH ERROR ProbableLockingFailure; END; logMapHandle: Handle _ GetOrReportOnLogMapHandle[file, TRUE]; MonitoredSetUncommittedSize[logMapHandle]; END; <> GetUncommittedSize: PUBLIC PROCEDURE[file: AI.FileHandle, trans: AI.TransHandle] RETURNS[size: AE.PageCount] = BEGIN -- non-fatal errors: none. MonitoredGetUncommittedSize: ENTRY PROCEDURE[logMapHandle: Handle] = INLINE BEGIN -- non-fatal errors: none. IF ((trans # logMapHandle.sizeUncommittedTrans) AND (logMapHandle.sizeUncommittedTrans # NIL)) THEN TRUSTED BEGIN IF TM.IsCommitted[logMapHandle.sizeUncommittedTrans] THEN RETURN WITH ERROR ProbableLockingFailure ELSE size _ LAST[AE.PageCount]; END ELSE size _ logMapHandle.sizeUncommitted; END; logMapHandle: Handle _ GetOrReportOnLogMapHandle[file, FALSE]; IF logMapHandle = NIL THEN RETURN[LAST[AE.PageCount]]; MonitoredGetUncommittedSize[logMapHandle]; END; <> SetCommittedSize: PUBLIC PROCEDURE[file: AI.FileHandle, size: AE.PageCount] = BEGIN -- non-fatal errors: none. MonitoredSetCommittedSize: ENTRY PROCEDURE[logMapHandle: Handle] = INLINE BEGIN -- non-fatal errors: none. logMapHandle.sizeCommitted _ size; END; logMapHandle: Handle _ GetOrReportOnLogMapHandle[file, TRUE]; MonitoredSetCommittedSize[logMapHandle]; END; <> GetCommittedSize: PUBLIC PROCEDURE[file: AI.FileHandle] RETURNS[size: AE.PageCount] = BEGIN -- non-fatal errors: none. MonitoredGetCommittedSize: ENTRY PROCEDURE[logMapHandle: Handle] = INLINE BEGIN -- non-fatal errors: none. size _ logMapHandle.sizeCommitted; END; logMapHandle: Handle _ GetOrReportOnLogMapHandle[file, FALSE]; IF logMapHandle = NIL THEN RETURN[LAST[AE.PageCount]]; MonitoredGetCommittedSize[logMapHandle]; END; <> SetCommittedHighWaterMark: PUBLIC PROCEDURE[file: AI.FileHandle, highWaterMark: AE.PageCount] = BEGIN -- non-fatal errors: none. MonitoredSetCommittedHighWaterMark: ENTRY PROCEDURE[logMapHandle: Handle] = INLINE BEGIN -- non-fatal errors: none. logMapHandle.highWaterMarkCommitted _ highWaterMark; END; logMapHandle: Handle _ GetOrReportOnLogMapHandle[file, TRUE]; MonitoredSetCommittedHighWaterMark[logMapHandle]; END; <> GetCommittedHighWaterMark: PUBLIC PROCEDURE[file: AI.FileHandle] RETURNS [highWaterMark: AE.PageCount] = BEGIN -- non-fatal errors: none. MonitoredGetCommittedHighWaterMark: ENTRY PROCEDURE[logMapHandle: Handle] = INLINE BEGIN -- non-fatal errors: none. highWaterMark _ logMapHandle.highWaterMarkCommitted; END; logMapHandle: Handle _ GetOrReportOnLogMapHandle[file, FALSE]; IF logMapHandle = NIL THEN RETURN[LAST[AE.PageCount]]; MonitoredGetCommittedHighWaterMark[logMapHandle]; END; <> SetLeaderPageHandle: PUBLIC PROCEDURE[file: AI.FileHandle, trans: AI.TransHandle, leaderPage: AI.LeaderPageHandle] = BEGIN -- non-fatal errors: Error[alreadySet]. MonitoredSetLeaderPageHandle: ENTRY PROCEDURE[logMapHandle: Handle] = INLINE BEGIN -- non-fatal errors: Error[alreadySet]. IF ((logMapHandle.leaderPageTrans = NIL) OR (trans = NIL) OR (logMapHandle.leaderPageTrans = trans)) THEN BEGIN logMapHandle.leaderPageTrans _ trans; logMapHandle.leaderPage _ leaderPage; RETURN; END ELSE BEGIN RETURN WITH ERROR ProbableLockingFailure END; END; logMapHandle: Handle _ GetOrReportOnLogMapHandle[file, TRUE]; MonitoredSetLeaderPageHandle[logMapHandle]; END; <> GetLeaderPageHandle: PUBLIC PROCEDURE[file: AI.FileHandle, trans: AI.TransHandle] RETURNS[leaderPage: AI.LeaderPageHandle] = BEGIN -- non-fatal errors: none. MonitoredGetLeaderPageHandle: ENTRY PROCEDURE[logMapHandle: Handle] = INLINE BEGIN -- non-fatal errors: none. leaderPage _ (IF trans = logMapHandle.leaderPageTrans THEN logMapHandle.leaderPage ELSE NIL); END; logMapHandle: Handle _ GetOrReportOnLogMapHandle[file, FALSE]; IF logMapHandle = NIL THEN RETURN[NIL]; MonitoredGetLeaderPageHandle[logMapHandle]; END; <> < for transaction trans, identified in the log by logRecordID. The log record contains exactly this pageRun. If writes are already registered for any of those pages by the same transaction, the old writes are forgotten. If writes are already registered for a different transaction, a fatal error is raised.>> RegisterPages: PUBLIC PROCEDURE[file: AI.FileHandle, trans: AI.TransHandle, pageRun: AE.PageRun, logRecordID: AI.LogRecordID] = BEGIN -- non-fatal errors: none. MonitoredRegisterPages: ENTRY PROCEDURE[logMapHandle: Handle] = BEGIN -- non-fatal errors: none. currentFirstPage: AE.PageNumber _ pageRun.firstPage; currentCount: INT _ pageRun.count; int: LMP.Intention _ RBTLookupNextSmaller[logMapHandle, currentFirstPage]; IF ((int # NIL) AND (int.pageRun.firstPage + int.pageRun.count > currentFirstPage)) THEN -- fission off the higher part. BEGIN higherPartInt: LMP.Intention _ IntentionZone.NEW[LMP.IntentionObject _ [int.trans, [currentFirstPage, int.pageRun.count - (currentFirstPage - int.pageRun.firstPage)], int.logRecordID, FALSE, , , ]]; RBTInsert[logMapHandle, higherPartInt, higherPartInt.pageRun.firstPage]; int.pageRun.count _ int.pageRun.count - higherPartInt.pageRun.count; int _ higherPartInt; END ELSE int _ RBTLookup[logMapHandle, currentFirstPage]; DO -- on entry int starts at currentFirstPage or is NIL if nothing starts there. IF int = NIL THEN BEGIN overlap: BOOLEAN; newInt: LMP.Intention; int _ RBTLookupNextLarger[logMapHandle, currentFirstPage]; overlap _ ((int # NIL) AND (int.pageRun.firstPage < currentFirstPage + currentCount)); newInt _ IntentionZone.NEW[LMP.IntentionObject _ [trans, [currentFirstPage, (IF overlap THEN int.pageRun.firstPage - currentFirstPage ELSE currentCount)], logRecordID, FALSE, , , ]]; -- newInt starts at currentFirstPage. RBTInsert[logMapHandle, newInt, newInt.pageRun.firstPage]; IF NOT overlap THEN EXIT; currentCount _ currentCount - newInt.pageRun.count; currentFirstPage _ int.pageRun.firstPage; END; <> IF ((int.trans # trans) OR (int.checkedOut)) THEN RETURN WITH ERROR ProbableLockingFailure; IF int.pageRun.count > currentCount THEN BEGIN -- fission off the higher part. higherPartInt: LMP.Intention _ IntentionZone.NEW[LMP.IntentionObject _ [trans, [currentFirstPage + currentCount, int.pageRun.count - currentCount], int.logRecordID, FALSE, , , ]]; RBTInsert[logMapHandle, higherPartInt, higherPartInt.pageRun.firstPage]; int.pageRun.count _ currentCount; END; int.logRecordID _ logRecordID; IF (currentCount _ currentCount - int.pageRun.count) = 0 THEN EXIT; currentFirstPage _ currentFirstPage + int.pageRun.count; int _ RBTLookup[logMapHandle, currentFirstPage]; ENDLOOP; END; logMapHandle: Handle _ GetOrReportOnLogMapHandle[file, TRUE]; TRUSTED BEGIN IF TM.IsCommitted[trans] THEN ERROR Horrible; END; MonitoredRegisterPages[logMapHandle]; END; < does not exactly match a checked out entry in the LogMap, a fatal error is raised.>> UnregisterPages: PUBLIC PROCEDURE[file: AI.FileHandle, pageRun: AE.PageRun] = BEGIN -- non-fatal errors: none. MonitoredUnregisterPages: ENTRY PROCEDURE[logMapHandle: Handle] = BEGIN -- non-fatal errors: none. intention: LMP.Intention _ RBTLookup[logMapHandle, pageRun.firstPage]; IF ((intention = NIL) OR (NOT intention.checkedOut) OR (intention.pageRun.count # pageRun.count)) THEN RETURN WITH ERROR Horrible; [] _ RBTDelete[logMapHandle, pageRun.firstPage]; BROADCAST IntentionFreed; END; logMapHandle: Handle _ GetOrReportOnLogMapHandle[file, FALSE]; IF logMapHandle = NIL THEN ERROR Horrible; MonitoredUnregisterPages[logMapHandle]; END; IntentionFreed: CONDITION; <> <> LocatePages: PUBLIC PROCEDURE[file: AI.FileHandle, trans: AI.TransHandle, pageRun: AE.PageRun, checkOut: LM.CheckOutOption] RETURNS[mappedPageRun: LM.MappedPageRun] = BEGIN -- non-fatal errors: Error[exceedsFileSize]. MonitoredLocatePages: ENTRY PROCEDURE[logMapHandle: Handle] RETURNS[mappedPageRun: LM.MappedPageRun] = BEGIN -- non-fatal errors: Error[exceedsFileSize]. int: LMP.Intention; currentCount: INT; DO IF pageRun.firstPage + pageRun.count > (IF logMapHandle.sizeUncommittedTrans = trans THEN logMapHandle.sizeUncommitted ELSE logMapHandle.sizeCommitted) THEN RETURN WITH ERROR Error[exceedsFileSize]; int _ RBTLookup[logMapHandle, pageRun.firstPage]; IF (int # NIL) THEN currentCount _ MIN[pageRun.count, int.pageRun.count] ELSE BEGIN int _ RBTLookupNextSmaller[logMapHandle, pageRun.firstPage]; IF ((int # NIL) AND (int.pageRun.firstPage + int.pageRun.count > pageRun.firstPage)) THEN currentCount _ MIN[int.pageRun.firstPage + int.pageRun.count, pageRun.firstPage + pageRun.count] - pageRun.firstPage ELSE BEGIN int _ RBTLookupNextLarger[logMapHandle, pageRun.firstPage]; IF int # NIL THEN BEGIN currentCount _ IF int.pageRun.firstPage < pageRun.firstPage + pageRun.count THEN int.pageRun.firstPage - pageRun.firstPage ELSE pageRun.count; int _ NIL; END ELSE currentCount _ pageRun.count; END; END; TRUSTED BEGIN IF ((int = NIL) OR ((int.trans # trans) AND (NOT TM.IsCommitted[int.trans]))) THEN RETURN[[[pageRun.firstPage, currentCount], base[]]]; END; IF int.trans = trans THEN RETURN[[[pageRun.firstPage, currentCount], log[int.logRecordID, int.pageRun, FALSE]]]; IF checkOut = checkOut THEN BEGIN IF int.checkedOut THEN BEGIN WAIT IntentionFreed; LOOP; END ELSE int.checkedOut _ TRUE; END; RETURN[[[pageRun.firstPage, currentCount], log[int.logRecordID, int.pageRun, (checkOut = checkOut)]]]; ENDLOOP; END; logMapHandle: Handle _ GetOrReportOnLogMapHandle[file, FALSE]; IF logMapHandle = NIL THEN RETURN[[pageRun, base[]]]; RETURN[MonitoredLocatePages[logMapHandle]]; END; <> LocateAnyPagesForTrans: PUBLIC PROCEDURE[file: AI.FileHandle, trans: AI.TransHandle] RETURNS[found: BOOLEAN, logRecordID: AI.LogRecordID, logMapPageRun: AE.PageRun] = BEGIN -- non-fatal errors: none. MonitoredLocateAnyPagesForTrans: ENTRY PROCEDURE[logMapHandle: Handle] = BEGIN -- non-fatal errors: none. FOR intention: LMP.Intention _ RBTLookupSmallest[logMapHandle], RBTLookupNextLarger[logMapHandle, intention.pageRun.firstPage] UNTIL intention = NIL DO IF ((intention.trans = trans) AND (NOT intention.checkedOut)) THEN BEGIN found _ TRUE; intention.checkedOut _ TRUE; logRecordID _ intention.logRecordID; logMapPageRun _ intention.pageRun; RETURN; END; ENDLOOP; DO FOR intention: LMP.Intention _ RBTLookupSmallest[logMapHandle], RBTLookupNextLarger[logMapHandle, intention.pageRun.firstPage] UNTIL intention = NIL DO IF intention.trans = trans THEN BEGIN IF (NOT intention.checkedOut) THEN RETURN WITH ERROR Horrible; WAIT IntentionFreed; EXIT; END; REPEAT FINISHED => GOTO allDone; ENDLOOP; REPEAT allDone => NULL; ENDLOOP; END; logMapHandle: Handle _ GetOrReportOnLogMapHandle[file, FALSE]; found _ FALSE; IF logMapHandle # NIL THEN MonitoredLocateAnyPagesForTrans[logMapHandle]; END; <> RegisterLeaderPage: PUBLIC PROCEDURE[file: AI.FileHandle, trans: AI.TransHandle, logRecordID: AI.LogRecordID] = BEGIN -- non-fatal errors: none. MonitoredRegisterLeaderPage: ENTRY PROCEDURE[logMapHandle: Handle] = INLINE BEGIN -- non-fatal errors: none. IF ((logMapHandle.leaderPageIntention.trans = NIL) OR (logMapHandle.leaderPageIntention.trans = trans)) THEN logMapHandle.leaderPageIntention _ [trans, logRecordID] ELSE RETURN WITH ERROR ProbableLockingFailure; END; logMapHandle: Handle _ GetOrReportOnLogMapHandle[file, TRUE]; MonitoredRegisterLeaderPage[logMapHandle]; END; <> UnregisterLeaderPage: PUBLIC PROCEDURE[file: AI.FileHandle] = BEGIN -- non-fatal errors: none. MonitoredUnregisterLeaderPage: ENTRY PROCEDURE[logMapHandle: Handle] = INLINE BEGIN -- non-fatal errors: none. logMapHandle.leaderPageIntention _ [NIL, [0, 0]]; END; logMapHandle: Handle _ GetOrReportOnLogMapHandle[file, FALSE]; IF logMapHandle = NIL THEN ERROR ProbableLockingFailure; MonitoredUnregisterLeaderPage[logMapHandle]; END; <> LocateLeaderPage: PUBLIC PROCEDURE[file: AI.FileHandle, trans: AI.TransHandle] RETURNS[location: LM.Location, logRecordID: AI.LogRecordID] = BEGIN -- non-fatal errors: none. MonitoredLocateLeaderPage: ENTRY PROCEDURE[logMapHandle: Handle] = INLINE BEGIN -- non-fatal errors: none. IF logMapHandle.leaderPageIntention.trans = trans THEN BEGIN location _ log; logRecordID _ logMapHandle.leaderPageIntention.logRecordID; END ELSE TRUSTED BEGIN IF ((logMapHandle.leaderPageIntention.trans = NIL) OR (NOT TM.IsCommitted[logMapHandle.leaderPageIntention.trans])) THEN location _ base ELSE RETURN WITH ERROR ProbableLockingFailure; END; END; logMapHandle: Handle _ GetOrReportOnLogMapHandle[file, FALSE]; IF logMapHandle = NIL THEN RETURN[base, [0, 0]]; MonitoredLocateLeaderPage[logMapHandle]; END; <> UnregisterTrans: PUBLIC PROCEDURE[file: AI.FileHandle, trans: AI.TransHandle] = BEGIN -- non-fatal errors: none. MonitoredUnregisterTrans: ENTRY PROCEDURE[logMapHandle: Handle] = BEGIN -- non-fatal errors: none. ClearTransFromLogMapHandle: INTERNAL PROCEDURE RETURNS[Handle] = BEGIN -- non system fatal errors: none. FOR intention: LMP.Intention _ RBTLookupSmallest[logMapHandle], RBTLookupNextLarger[logMapHandle, intention.pageRun.firstPage] UNTIL intention = NIL DO IF intention.trans = trans THEN BEGIN IF intention.checkedOut THEN RETURN WITH ERROR Horrible; [] _ RBTDelete[logMapHandle, intention.pageRun.firstPage]; END; ENDLOOP; IF logMapHandle.createTrans = trans THEN logMapHandle.createTrans _ NIL; IF logMapHandle.deleteTrans = trans THEN logMapHandle.deleteTrans _ NIL; IF logMapHandle.versionUncommittedTrans = trans THEN BEGIN logMapHandle.versionUncommittedTrans _ NIL; logMapHandle.versionUncommitted _ 0; END; IF logMapHandle.sizeUncommittedTrans = trans THEN BEGIN logMapHandle.sizeUncommittedTrans _ NIL; logMapHandle.sizeUncommitted _ LAST[AE.PageCount]; END; IF logMapHandle.leaderPageTrans = trans THEN BEGIN logMapHandle.leaderPageTrans _ NIL; logMapHandle.leaderPage _ NIL; END; IF logMapHandle.leaderPageIntention.trans = trans THEN logMapHandle.leaderPageIntention _ [NIL, [0, 0]]; IF ((RBTLookupSmallest[logMapHandle] = NIL) AND (logMapHandle.createTrans = NIL) AND (logMapHandle.deleteTrans = NIL) AND (logMapHandle.versionUncommittedTrans = NIL) AND (logMapHandle.sizeUncommittedTrans = NIL) AND (logMapHandle.leaderPageTrans = NIL) AND (logMapHandle.leaderPageIntention.trans = NIL)) THEN RETURN[NIL] ELSE RETURN[logMapHandle]; END; FileMap.ClearLogMapHandle[file, ClearTransFromLogMapHandle]; END; logMapHandle: Handle _ GetOrReportOnLogMapHandle[file, FALSE]; IF logMapHandle # NIL THEN MonitoredUnregisterTrans[logMapHandle]; END; <> GetKeyProc: RedBlackTree.GetKey -- PROC [data: UserData] RETURNS [Key] = { RETURN[ data ]; }; CompareProc: RedBlackTree.Compare -- PROC [k: Key, data: UserData] RETURNS [Basics.Comparison] = { dataIntention: LMP.Intention = NARROW[ data ]; WITH k SELECT FROM pnRef: REF AE.PageNumber => RETURN[Basics.CompareINT[pnRef^, dataIntention.pageRun.firstPage]]; keyIntention: LMP.Intention => RETURN[Basics.CompareINT[keyIntention.pageRun.firstPage, dataIntention.pageRun.firstPage]]; ENDCASE => ERROR; }; <> GetOrReportOnLogMapHandle: PROCEDURE[fileHandle: FileMap.Handle, create: BOOLEAN] RETURNS[logMapHandle: Handle] = BEGIN -- non system fatal errors: none. CreateLogMapHandle: PROCEDURE RETURNS[logMapHandle: Handle] = BEGIN -- non system fatal errors: none. logMapHandle _ IF create THEN LogMapObjectZone.NEW[LogMapObject _ [ createTrans: NIL, deleteTrans: NIL, versionUncommitted: 0, versionUncommittedTrans: NIL, versionCommitted: 0, sizeUncommitted: LAST[AE.PageCount], sizeUncommittedTrans: NIL, sizeCommitted: LAST[AE.PageCount], highWaterMarkCommitted: LAST[AE.PageCount], leaderPage: NIL, leaderPageTrans: NIL, intentionsTable: RedBlackTree.Create[getKey: GetKeyProc, compare: CompareProc], leaderPageIntention: [trans: NIL, logRecordID: [0, 0]], rbKeyRef: NEW[AE.PageNumber _ 0]] ] ELSE NIL; END; logMapHandle _ FileMap.VerifyLogMapHandle[fileHandle, CreateLogMapHandle]; END; <> RBTLookupProc: TYPE = PROCEDURE[ logMapHandle: Handle, key: AlpineEnvironment.PageNumber ] RETURNS [LMP.Intention]; RBTLookup: INTERNAL RBTLookupProc = { logMapHandle.rbKeyRef^ _ key; RETURN[ NARROW[RedBlackTree.Lookup[ logMapHandle.intentionsTable, logMapHandle.rbKeyRef]] ]; }; RBTLookupNextLarger: INTERNAL RBTLookupProc = { logMapHandle.rbKeyRef^ _ key; RETURN[ NARROW[RedBlackTree.LookupNextLarger[ logMapHandle.intentionsTable, logMapHandle.rbKeyRef]] ]; }; RBTLookupNextSmaller: INTERNAL RBTLookupProc = { logMapHandle.rbKeyRef^ _ key; RETURN[ NARROW[RedBlackTree.LookupNextSmaller[ logMapHandle.intentionsTable, logMapHandle.rbKeyRef]] ]; }; RBTLookupLargest: INTERNAL PROCEDURE[ logMapHandle: Handle ] RETURNS [LMP.Intention] = { RETURN[ NARROW[RedBlackTree.LookupLargest[ logMapHandle.intentionsTable]] ]; }; RBTLookupSmallest: INTERNAL PROCEDURE[ logMapHandle: Handle ] RETURNS [LMP.Intention] = { RETURN[ NARROW[RedBlackTree.LookupSmallest[ logMapHandle.intentionsTable ]] ]; }; RBTDelete: INTERNAL PROCEDURE[ logMapHandle: Handle, key: AlpineEnvironment.PageNumber ] RETURNS [LMP.Intention] = { n: RedBlackTree.Node; logMapHandle.rbKeyRef^ _ key; n _ RedBlackTree.Delete[ logMapHandle.intentionsTable, logMapHandle.rbKeyRef]; RETURN[ IF n=NIL THEN NIL ELSE NARROW[n.data] ]; }; RBTInsert: INTERNAL PROCEDURE[ logMapHandle: Handle, refChunk: LMP.Intention, key: AlpineEnvironment.PageNumber ] = { logMapHandle.rbKeyRef^ _ key; RedBlackTree.Insert[ logMapHandle.intentionsTable, refChunk, logMapHandle.rbKeyRef ]; }; <
> LogMapObjectZone: ZONE _ SafeStorage.GetSystemZone[]; IntentionZone: ZONE _ SafeStorage.GetSystemZone[]; END. <> <> <> <<>>