ReadEntry:
PUBLIC
ENTRY
UNSAFE
PROC [hashTable: ExtendibleHash.ExtendibleHashTable, hashValue: ExtendibleHash.HashValue, proc:
UNSAFE
PROC [entry: ExtendibleHash.Entry, wordsForEntriesOnPage:
INT, overFlowPageProc:
UNSAFE
PROC
RETURNS [entry: ExtendibleHash.Entry, wordsForEntriesOnPage:
INT]], clientPerCallData:
REF ←
NIL] ~ {
ENABLE UNWIND => {};
overFlowPageProc: UNSAFE PROC RETURNS [entry: ExtendibleHash.Entry, wordsForEntriesOnPage: INT] ~ {RETURN[NIL, 0]}; -- overflow not implemented
dictionaryPage: WORD;
virtualPage: ExtendibleHash.PageNumber;
pagePtr: ExtendibleHash.PagePtr;
hashPagePtr: LONG POINTER TO ExtendibleHashInternal.HashPage;
dictionaryPage ← PBasics.BITAND[hashValue.low, hashTable.hashMask.low];
virtualPage ← hashTable.dictionary[dictionaryPage];
pagePtr ← hashTable.RefPage[virtualPage, read, clientPerCallData];
hashPagePtr ← LOOPHOLE[pagePtr];
TRUSTED {proc[entry: LOOPHOLE[@hashPagePtr.entries], wordsForEntriesOnPage: hashPagePtr.usedWords, overFlowPageProc: overFlowPageProc];};
hashTable.RelPage[virtualPage, unchanged, clientPerCallData];
};
DeleteEntry:
PUBLIC
ENTRY
UNSAFE
PROC [hashTable: ExtendibleHash.ExtendibleHashTable, hashValue: ExtendibleHash.HashValue, proc:
UNSAFE
PROC [entry: ExtendibleHash.Entry, wordsForEntriesOnPage:
INT, overFlowPageProc:
UNSAFE
PROC
RETURNS [entry: ExtendibleHash.Entry, wordsForEntriesOnPage:
INT]]
RETURNS [entryToDelete: ExtendibleHash.Entry], clientPerCallData:
REF ←
NIL] ~ {
ENABLE UNWIND => {};
overFlowPageProc: UNSAFE PROC RETURNS [entry: ExtendibleHash.Entry, wordsForEntriesOnPage: INT] ~ {RETURN[NIL, 0]}; -- overflow not implemented
dictionaryPage: WORD;
virtualPage: ExtendibleHash.PageNumber;
pagePtr: ExtendibleHash.PagePtr;
hashPagePtr: LONG POINTER TO ExtendibleHashInternal.HashPage;
entryToDelete: ExtendibleHash.Entry;
dictionaryPage ← PBasics.BITAND[hashValue.low, hashTable.hashMask.low];
virtualPage ← hashTable.dictionary[dictionaryPage];
pagePtr ← hashTable.RefPage[virtualPage, write, clientPerCallData];
hashPagePtr ← LOOPHOLE[pagePtr];
TRUSTED {entryToDelete ← proc[entry: LOOPHOLE[@hashPagePtr.entries], wordsForEntriesOnPage: hashPagePtr.usedWords, overFlowPageProc: overFlowPageProc];};
IF entryToDelete #
NIL
THEN
TRUSTED {
nowEntry: ExtendibleHash.Entry ← LOOPHOLE[@hashPagePtr.entries];
wordsLeft: INT ← hashPagePtr.usedWords;
WHILE wordsLeft > 0
DO
IF nowEntry = entryToDelete THEN EXIT;
wordsLeft ← wordsLeft - nowEntry.entryWordSize - 1;
nowEntry ← nowEntry + ((nowEntry.entryWordSize + 1) * UNITS[CARD32]);
REPEAT FINISHED => ERROR Error[notAnEntry];
ENDLOOP;
hashPagePtr.usedWords ← hashPagePtr.usedWords - nowEntry.entryWordSize - 1;
hashPagePtr.freeWords ← hashPagePtr.freeWords + nowEntry.entryWordSize + 1;
PBasics.Move[src: nowEntry + ((nowEntry.entryWordSize + 1) * UNITS[CARD32]), dst: nowEntry, nWords: wordsLeft - nowEntry.entryWordSize];
{
checkEntry: ExtendibleHash.Entry ← LOOPHOLE[@hashPagePtr.entries];
checkWordsLeft: INT ← hashPagePtr.usedWords;
WHILE checkWordsLeft > 0
DO
IF checkEntry.entryWordSize > hashPagePtr.usedWords OR checkEntry.entryWordSize > hashTable.state.pageSize OR checkEntry.entryWordSize = 0 THEN ERROR;
IF (checkWordsLeft ← checkWordsLeft - checkEntry.entryWordSize - 1) < 0 THEN ERROR;
checkEntry ← checkEntry + ((checkEntry.entryWordSize + 1) * UNITS[CARD32]);
ENDLOOP;
};
hashTable.RelPage[virtualPage, modified, clientPerCallData];
}
ELSE hashTable.RelPage[virtualPage, unchanged, clientPerCallData];
};
UpdateEntry:
PUBLIC
ENTRY UNSAFE
PROC [
hashTable: ExtendibleHash.ExtendibleHashTable,
hashValue: ExtendibleHash.HashValue,
words: ExtendibleHash.EntSize,
findProc: UNSAFE PROC [entry: ExtendibleHash.Entry, wordsForEntriesOnPage: INT, overFlowPageProc: UNSAFE PROC RETURNS [entry: ExtendibleHash.Entry, wordsForEntriesOnPage: INT]] RETURNS [entryToUpdate: ExtendibleHash.Entry],
modifyProc: UNSAFE PROC [entry: ExtendibleHash.Entry],
updateType: ExtendibleHash.UpdateType ← insertOrReplace,
clientPerCallData: REF ← NIL] ~ {
ENABLE UNWIND => {};
overFlowPageProc: UNSAFE PROC RETURNS [entry: ExtendibleHash.Entry, wordsForEntriesOnPage: INT] ~ {RETURN[NIL, 0]}; -- overflow not implemented
dictionaryPage: WORD;
virtualPage: ExtendibleHash.PageNumber;
pagePtr: ExtendibleHash.PagePtr;
hashPagePtr: LONG POINTER TO ExtendibleHashInternal.HashPage;
entryToUpdate: ExtendibleHash.Entry;
nextEntry: ExtendibleHash.Entry ← NIL;
savedNextWordSize: CARD32 ← CARD32.LAST;
dictionaryPage ← PBasics.BITAND[hashValue.low, hashTable.hashMask.low];
virtualPage ← hashTable.dictionary[dictionaryPage];
pagePtr ← hashTable.RefPage[virtualPage, write, clientPerCallData];
hashPagePtr ← LOOPHOLE[pagePtr];
TRUSTED {entryToUpdate ← findProc[entry: LOOPHOLE[@hashPagePtr.entries], wordsForEntriesOnPage: hashPagePtr.usedWords, overFlowPageProc: overFlowPageProc];};
SELECT updateType
FROM
insert => IF entryToUpdate # NIL THEN ERROR Error[wrongUpdateType];
replace => IF entryToUpdate = NIL THEN ERROR Error[wrongUpdateType];
ENDCASE;
IF entryToUpdate #
NIL
THEN
TRUSTED {
nowEntry: ExtendibleHash.Entry ← LOOPHOLE[@hashPagePtr.entries];
wordsLeft: INT ← hashPagePtr.usedWords;
WHILE wordsLeft > 0
DO
IF nowEntry = entryToUpdate THEN EXIT;
wordsLeft ← wordsLeft - nowEntry.entryWordSize - 1;
nowEntry ← nowEntry + ((nowEntry.entryWordSize + 1) * UNITS[CARD32]);
REPEAT FINISHED => ERROR Error[notAnEntry];
ENDLOOP;
IF entryToUpdate.entryWordSize # words
THEN {
IF INT[hashPagePtr.freeWords] < (INT[words] - INT[nowEntry.entryWordSize]) THEN ERROR Error[outOfRoom];
hashPagePtr.usedWords ← (hashPagePtr.usedWords + words) - entryToUpdate.entryWordSize;
hashPagePtr.freeWords ← (hashPagePtr.freeWords + nowEntry.entryWordSize) - words;
PBasics.Move[src: nowEntry + ((nowEntry.entryWordSize + 1) * UNITS[CARD32]), dst: nowEntry + ((words + 1) * UNITS[CARD32]), nWords: wordsLeft - nowEntry.entryWordSize - 1];
entryToUpdate.entryWordSize ← words;
};
nextEntry ← entryToUpdate + ((words + 1) * UNITS[CARD32]);
IF hashPagePtr.freeWords > 0 THEN savedNextWordSize ← nextEntry.entryWordSize;
modifyProc[entryToUpdate];
IF entryToUpdate.entryWordSize # words THEN ERROR Error[entrySizesWrong];
IF hashPagePtr.freeWords > 0
THEN {
IF nextEntry.entryWordSize # savedNextWordSize THEN ERROR Error[overWriteOfNextEntry];
};
hashTable.RelPage[virtualPage, modified, clientPerCallData];
}
ELSE
TRUSTED {
IF hashPagePtr.freeWords + 1 < words THEN ERROR Error[outOfRoom];
entryToUpdate ← LOOPHOLE[@hashPagePtr.entries + UNITS[CARD32] * hashPagePtr.usedWords];
hashPagePtr.usedWords ← hashPagePtr.usedWords + words + 1;
hashPagePtr.freeWords ← hashPagePtr.freeWords - words - 1;
entryToUpdate.entryWordSize ← words;
nextEntry ← entryToUpdate + ((words + 1) * UNITS[CARD32]);
IF hashPagePtr.freeWords > 0 THEN savedNextWordSize ← nextEntry.entryWordSize;
modifyProc[entryToUpdate];
IF entryToUpdate.entryWordSize # words THEN ERROR Error[entrySizesWrong];
IF hashPagePtr.freeWords > 0
THEN {
IF nextEntry.entryWordSize # savedNextWordSize THEN ERROR Error[overWriteOfNextEntry];
};
hashTable.RelPage[virtualPage, unchanged, clientPerCallData];
};
};