summaryrefslogtreecommitdiff
path: root/src/md/hotdata/hottable.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/md/hotdata/hottable.cpp')
-rw-r--r--src/md/hotdata/hottable.cpp138
1 files changed, 138 insertions, 0 deletions
diff --git a/src/md/hotdata/hottable.cpp b/src/md/hotdata/hottable.cpp
new file mode 100644
index 0000000000..51efe1bf94
--- /dev/null
+++ b/src/md/hotdata/hottable.cpp
@@ -0,0 +1,138 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+// File: HotTable.cpp
+//
+
+//
+// Class code:MetaData::HotTable stores hot table records cache, a cache of often-accessed
+// table records stored only in NGEN images.
+// The cache is created using IBC logging.
+//
+// ======================================================================================
+
+#include "external.h"
+
+#include "hottable.h"
+#include "hotdataformat.h"
+
+#include <metamodelpub.h>
+
+namespace MetaData
+{
+
+// --------------------------------------------------------------------------------------
+//
+// Returns S_OK if index (nIndex) is present in the hot table record cache and returns its value from
+// cache (*ppRecord).
+// Returns S_FALSE if offset is not in the hot table record cache, DOES NOT initialize *ppRecord in this
+// case!
+// Returns error code otherwise (and sets *pRecord to NULL).
+//
+
+//static
+__checkReturn
+HRESULT
+HotTable::GetData(
+ UINT32 nRowIndex,
+ __deref_out_opt BYTE **ppRecord,
+ UINT32 cbRecordSize,
+ struct HotTableHeader *pHotTableHeader)
+{
+ BYTE *pHotTableHeaderData = (BYTE *)pHotTableHeader;
+
+ if (pHotTableHeader->m_nFirstLevelTable_PositiveOffset != 0)
+ { // Has first level table
+ // fetch the first level table
+ WORD *pFirstLevelTable = (WORD *)(pHotTableHeaderData + pHotTableHeader->m_nFirstLevelTable_PositiveOffset);
+
+ // find the high order bits of the rid
+ BYTE bRid = (BYTE)(nRowIndex >> pHotTableHeader->m_shiftCount);
+
+ // use the low order bits of the rid to index into
+ // the first level table.
+ UINT32 nMask = (1 << pHotTableHeader->m_shiftCount) - 1;
+ int i = pFirstLevelTable[nRowIndex & nMask];
+ int end = pFirstLevelTable[(nRowIndex & nMask) + 1];
+
+ // the generation logic should make sure either all tables are present
+ // or all absent.
+ _ASSERTE(pHotTableHeader->m_nSecondLevelTable_PositiveOffset != 0);
+ _ASSERTE(pHotTableHeader->m_offsIndexMappingTable != 0);
+
+ // fetch second level and index mapping tables
+ BYTE *pSecondLevelTable = pHotTableHeaderData + pHotTableHeader->m_nSecondLevelTable_PositiveOffset;
+ WORD *pIndexMappingTable = (WORD *)(pHotTableHeaderData + pHotTableHeader->m_offsIndexMappingTable);
+
+ // look for the high order bits of the rid in the second level table.
+ // search is linear, but should be short on average.
+ for ( ; i < end; i++)
+ {
+ if (pSecondLevelTable[i] == bRid)
+ {
+ // we have found the hot rid we are looking for
+
+ // now consult the index mapping table to find where the hot data is stored
+ int index = pIndexMappingTable[i];
+
+ *ppRecord = pHotTableHeaderData + pHotTableHeader->m_offsHotData + (index * cbRecordSize);
+ return S_OK;
+ }
+ }
+ // Not found in hot data
+ return S_FALSE;
+ }
+ // no first level table - this implies the whole table is replicated
+ // in the hot section. simply multiply and fetch the right record.
+ // hot indices are 0-based, rids are 1-base, so need to subtract 1 from rid.
+
+ *ppRecord = pHotTableHeaderData + pHotTableHeader->m_offsHotData + ((nRowIndex - 1) * cbRecordSize);
+ return S_OK;
+} // HotTable::GetData
+
+// static
+void
+HotTable::CheckTables(struct HotTablesDirectory *pHotTablesDirectory)
+{
+#ifdef _DEBUG
+ _ASSERTE(pHotTablesDirectory->m_nMagic == HotTablesDirectory::const_nMagic);
+
+ for (UINT32 nTableIndex = 0; nTableIndex < TBL_COUNT; nTableIndex++)
+ {
+ if (pHotTablesDirectory->m_rgTableHeader_SignedOffset[nTableIndex] != 0)
+ {
+ struct HotTableHeader *pHotTableHeader = GetTableHeader(pHotTablesDirectory, nTableIndex);
+
+ _ASSERTE((pHotTableHeader->m_cTableRecordCount > 0) && (pHotTableHeader->m_cTableRecordCount <= USHRT_MAX));
+ if (pHotTableHeader->m_nFirstLevelTable_PositiveOffset == 0)
+ {
+ _ASSERTE(pHotTableHeader->m_nSecondLevelTable_PositiveOffset == 0);
+ _ASSERTE(pHotTableHeader->m_offsIndexMappingTable == 0);
+ _ASSERTE(pHotTableHeader->m_offsHotData == Align4(sizeof(struct HotTableHeader)));
+ }
+ else
+ {
+ UINT32 nFirstLevelTableOffset = sizeof(struct HotTableHeader);
+ _ASSERTE(pHotTableHeader->m_nFirstLevelTable_PositiveOffset == nFirstLevelTableOffset);
+ UINT32 cbFirstLevelTableSize = sizeof(WORD) * ((1 << pHotTableHeader->m_shiftCount) + 1);
+
+ _ASSERTE(pHotTableHeader->m_nSecondLevelTable_PositiveOffset != 0);
+ UINT32 nSecondLevelTableOffset = nFirstLevelTableOffset + cbFirstLevelTableSize;
+ _ASSERTE(pHotTableHeader->m_nSecondLevelTable_PositiveOffset == nSecondLevelTableOffset);
+ UINT32 cbSecondLevelTableSize = sizeof(BYTE) * pHotTableHeader->m_cTableRecordCount;
+
+ _ASSERTE(pHotTableHeader->m_offsIndexMappingTable != 0);
+ UINT32 nIndexMappingTableOffset = nSecondLevelTableOffset + cbSecondLevelTableSize;
+ _ASSERTE(pHotTableHeader->m_offsIndexMappingTable == nIndexMappingTableOffset);
+ UINT32 cbIndexMappingTableSize = sizeof(WORD) * pHotTableHeader->m_cTableRecordCount;
+
+ UINT32 nHotDataOffset = nIndexMappingTableOffset + cbIndexMappingTableSize;
+ _ASSERTE(pHotTableHeader->m_offsHotData == Align4(nHotDataOffset));
+ }
+ }
+ }
+#endif //_DEBUG
+} // HotTable::CheckTables
+
+}; // namespace MetaData