#ifndef _BPLUSTREE_CPP #define _BPLUSTREE_CPP /* * Class: * * WmiAllocator * * Description: * * Provides abstraction above heap allocation functions * * Version: * * Initial * * Last Changed: * * See Source Depot for change history * */ #if 0 #include #include #include #include #endif #if 0 #define INSERT_DEBUG #define DELETE_DEBUG #define FIND_DEBUG #define COMMON_DEBUG #endif /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ WmiBPlusTree :: WmiBPlusTree ( WmiAllocator &a_Allocator , WmiBlockInterface &a_BlockAllocator , GUID &a_Identifier , ULONG a_BlockSize , ULONG a_KeyType , ULONG a_KeyTypeLength , ComparatorFunction a_ComparatorFunction , void *a_ComparatorOperand ) : m_Allocator ( a_Allocator ) , m_BlockAllocator ( a_BlockAllocator ) , m_Size ( 0 ) , m_Root ( 0 ) , m_Identifier ( a_Identifier ) , m_BlockSize ( a_BlockSize ) , m_KeyType ( a_KeyType ) , m_KeyTypeLength ( a_KeyTypeLength ) , m_ComparatorFunction ( a_ComparatorFunction ) , m_ComparatorOperand ( a_ComparatorOperand ) { } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ WmiBPlusTree :: ~WmiBPlusTree () { WmiStatusCode t_StatusCode = UnInitialize () ; } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ WmiStatusCode WmiBPlusTree :: Initialize () { WmiStatusCode t_StatusCode = e_StatusCode_Success ; return t_StatusCode ; } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ WmiStatusCode WmiBPlusTree :: UnInitialize () { WmiStatusCode t_StatusCode = e_StatusCode_Success ; if ( m_Root ) { t_StatusCode = RecursiveUnInitialize ( m_Root ) ; m_Root = NULL ; } return t_StatusCode ; } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ WmiStatusCode WmiBPlusTree :: RecursiveUnInitialize ( WmiAbsoluteBlockOffSet &a_BlockOffSet ) { WmiStatusCode t_StatusCode = e_StatusCode_Success ; return t_StatusCode ; } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ void WmiBPlusTree :: Recurse () { OutputDebugString ( L"\nXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" ) ; if ( m_Root ) { BYTE *t_Block = NULL ; WmiStatusCode t_StatusCode = m_BlockAllocator.ReadBlock ( 1 , m_Root , t_Block ) ; if ( t_StatusCode == e_StatusCode_Success ) { WmiBPKeyNode *t_Node = ( WmiBPKeyNode * ) t_Block ; Recurse ( t_Node , m_Root ) ; m_BlockAllocator.ReleaseBlock ( t_Block ) ; } } OutputDebugString ( L"\nXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" ) ; } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ void WmiBPlusTree :: Recurse ( WmiBPKeyNode *a_Node , WmiAbsoluteBlockOffSet &a_BlockOffSet ) { WmiStatusCode t_StatusCode = e_StatusCode_Success ; wchar_t t_StringBuffer [ 1024 ] ; swprintf ( t_StringBuffer , L"\n(%I64x)" , a_BlockOffSet ) ; OutputDebugString ( t_StringBuffer ) ; WmiAbsoluteBlockOffSet t_BlockOffSet = sizeof ( WmiBPKeyNode ) ; ULONG t_InternalKeySize = GetKeyTypeLength () ; ULONG t_KeyOffSet ; BOOL t_Leaf = ( ( a_Node->GetFlags () & WMIBPLUS_TREE_FLAG_LEAF ) == WMIBPLUS_TREE_FLAG_LEAF ) ; if ( t_Leaf ) { t_KeyOffSet = WmiBlockLeafKeyOffSet ; t_InternalKeySize = t_InternalKeySize + WmiBlockLeafKeyOffSet ; } else { t_KeyOffSet = WmiBlockKeyOffSet ; t_InternalKeySize = t_InternalKeySize + WmiBlockKeyOffSet ; } ULONG t_NodeStart = a_Node->GetNodeStart () ; ULONG t_NodeSize = a_Node->GetNodeSize () ; if ( t_Leaf ) { if ( a_BlockOffSet == m_Root ) { } else { if ( a_Node->GetNodeSize () < ( MaxLeafKeys () >> 1 ) ) { OutputDebugString ( L"\nInvalid Leaf Balance" ) ; } } for ( ULONG t_Index = t_NodeStart ; t_Index < t_NodeSize ; t_Index ++ ) { BYTE *t_Buffer = ( ( BYTE * ) a_Node ) + t_BlockOffSet + t_KeyOffSet ; WmiBPKey t_Key ( t_Buffer , GetKeyTypeLength () ) ; #if 0 wchar_t t_StringBuffer [ 1024 ] ; swprintf ( t_StringBuffer , L"\nKey = %I64x" , * ( UINT64 * ) t_Key.GetConstData () ) ; OutputDebugString ( t_StringBuffer ) ; #endif t_BlockOffSet = t_BlockOffSet + t_InternalKeySize ; } } else { if ( a_BlockOffSet == m_Root ) { } else { if ( a_Node->GetNodeSize () < ( MaxKeys () >> 1 ) ) { OutputDebugString ( L"\nInvalid Balance" ) ; } } for ( ULONG t_Index = t_NodeStart ; t_Index <= t_NodeSize ; t_Index ++ ) { BYTE *t_Buffer = ( ( BYTE * ) a_Node ) + t_BlockOffSet + t_KeyOffSet ; WmiAbsoluteBlockOffSet t_ChildOffSet = 0 ; CopyMemory ( ( BYTE * ) & t_ChildOffSet , ( ( BYTE * ) ( a_Node ) ) + t_BlockOffSet + WmiBlockKeyPointerOffSet , sizeof ( WmiAbsoluteBlockOffSet ) ) ; wchar_t t_StringBuffer [ 1024 ] ; swprintf ( t_StringBuffer , L"\t(%I64x)" , t_ChildOffSet ) ; OutputDebugString ( t_StringBuffer ) ; t_BlockOffSet = t_BlockOffSet + t_InternalKeySize ; } t_BlockOffSet = sizeof ( WmiBPKeyNode ) ; for ( t_Index = t_NodeStart ; t_Index <= t_NodeSize ; t_Index ++ ) { BYTE *t_Buffer = ( ( BYTE * ) a_Node ) + t_BlockOffSet + t_KeyOffSet ; WmiAbsoluteBlockOffSet t_ChildOffSet = 0 ; CopyMemory ( ( BYTE * ) & t_ChildOffSet , ( ( BYTE * ) ( a_Node ) ) + t_BlockOffSet + WmiBlockKeyPointerOffSet , sizeof ( WmiAbsoluteBlockOffSet ) ) ; BYTE *t_Block = NULL ; t_StatusCode = m_BlockAllocator.ReadBlock ( 1 , t_ChildOffSet , t_Block ) ; if ( t_StatusCode == e_StatusCode_Success ) { WmiBPKeyNode *t_Node = ( WmiBPKeyNode * ) t_Block ; Recurse ( t_Node , t_ChildOffSet ) ; m_BlockAllocator.ReleaseBlock ( t_Block ) ; } if ( t_Index < t_NodeSize ) { #if 0 WmiBPKey t_Key ( t_Buffer , GetKeyTypeLength () ) ; wchar_t t_StringBuffer [ 1024 ] ; swprintf ( t_StringBuffer , L"\nKey = %I64x" , * ( UINT64 * ) t_Key.GetConstData () ) ; OutputDebugString ( t_StringBuffer ) ; #endif } t_BlockOffSet = t_BlockOffSet + t_InternalKeySize ; } } } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ void WmiBPlusTree :: PrintNode ( wchar_t *a_Prefix , WmiBPKeyNode *a_Node , WmiAbsoluteBlockOffSet &a_BlockOffSet ) { WmiAbsoluteBlockOffSet t_BlockOffSet = sizeof ( WmiBPKeyNode ) ; ULONG t_InternalKeySize = GetKeyTypeLength () ; ULONG t_KeyOffSet ; ULONG t_KeyPtrOffSet ; BOOL t_Leaf = ( ( a_Node->GetFlags () & WMIBPLUS_TREE_FLAG_LEAF ) == WMIBPLUS_TREE_FLAG_LEAF ) ; if ( t_Leaf ) { t_KeyOffSet = WmiBlockLeafKeyOffSet ; t_InternalKeySize = t_InternalKeySize + WmiBlockLeafKeyOffSet ; } else { t_KeyOffSet = WmiBlockKeyOffSet ; t_KeyPtrOffSet = WmiBlockKeyPointerOffSet ; t_InternalKeySize = t_InternalKeySize + WmiBlockKeyOffSet ; } ULONG t_NodeStart = a_Node->GetNodeStart () ; ULONG t_NodeSize = a_Node->GetNodeSize () ; OutputDebugString ( L"\n======================================" ) ; OutputDebugString ( a_Prefix ) ; if ( t_Leaf ) { OutputDebugString ( L"\nLeaf" ) ; if ( a_BlockOffSet == m_Root ) { OutputDebugString ( L"\nRoot" ) ; } else { if ( a_Node->GetNodeSize () < ( MaxLeafKeys () >> 1 ) ) { OutputDebugString ( L"\nInvalid Balance" ) ; } } } else { OutputDebugString ( L"\nInternal" ) ; if ( a_BlockOffSet == m_Root ) { OutputDebugString ( L"\nRoot" ) ; } else { if ( a_Node->GetNodeSize () < ( MaxKeys () >> 1 ) ) { OutputDebugString ( L"\nInvalid Balance" ) ; } } } wchar_t t_StringBuffer [ 1024 ] ; swprintf ( t_StringBuffer , L"\n%I64x" , a_BlockOffSet ) ; OutputDebugString ( t_StringBuffer ) ; OutputDebugString ( L"\n--------------------------------------" ) ; for ( ULONG t_Index = t_NodeStart ; t_Index < t_NodeSize ; t_Index ++ ) { BYTE *t_KeyBuffer = ( ( BYTE * ) a_Node ) + t_BlockOffSet + t_KeyOffSet ; if ( t_Leaf ) { WmiBPElement t_Element = 0 ; CopyMemory ( ( BYTE * ) & t_Element , ( ( BYTE * ) ( a_Node ) ) + t_BlockOffSet + WmiBlockLeafKeyElementOffSet , sizeof ( WmiAbsoluteBlockOffSet ) ) ; swprintf ( t_StringBuffer , L"\n(%I64x,%I64x)" , * ( UINT64 * ) t_KeyBuffer , t_Element ) ; } else { BYTE *t_LeftPointerBuffer = ( ( BYTE * ) a_Node ) + t_BlockOffSet + t_KeyPtrOffSet ; BYTE *t_RightPointerBuffer = ( ( BYTE * ) a_Node ) + t_BlockOffSet + t_KeyPtrOffSet + t_InternalKeySize ; WmiBPElement t_Element = 0 ; CopyMemory ( ( BYTE * ) & t_Element , ( ( BYTE * ) ( a_Node ) ) + t_BlockOffSet + WmiBlockKeyElementOffSet , sizeof ( WmiAbsoluteBlockOffSet ) ) ; swprintf ( t_StringBuffer , L"\n(%I64x),(%I64x,%I64x),(%I64x)" , * ( UINT64 * ) t_LeftPointerBuffer , * ( UINT64 * ) t_KeyBuffer , t_Element , * ( UINT64 * ) t_RightPointerBuffer ) ; } OutputDebugString ( t_StringBuffer ) ; t_BlockOffSet = t_BlockOffSet + t_InternalKeySize ; } OutputDebugString ( L"\n======================================" ) ; } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ WmiStatusCode WmiBPlusTree :: PositionInBlock ( WmiBPKeyNode *a_Node , WmiAbsoluteBlockOffSet &a_BlockOffSet , ULONG &a_NodeIndex , WmiRelativeBlockOffSet &a_NodeOffSet , WmiAbsoluteBlockOffSet &a_ChildOffSet ) { WmiStatusCode t_StatusCode = e_StatusCode_Success ; #ifdef COMMON_DEBUG PrintNode ( L"\nFindNextInBlock" , a_Node , a_BlockOffSet ) ; #endif ULONG t_InternalKeySize = GetKeyTypeLength () ; BOOL t_Leaf = ( ( a_Node->GetFlags () & WMIBPLUS_TREE_FLAG_LEAF ) == WMIBPLUS_TREE_FLAG_LEAF ) ; if ( t_Leaf ) { t_InternalKeySize = t_InternalKeySize + WmiBlockLeafKeyOffSet ; } else { t_InternalKeySize = t_InternalKeySize + WmiBlockKeyOffSet ; } ULONG t_NodeStart = a_Node->GetNodeStart () ; ULONG t_NodeSize = a_Node->GetNodeSize () ; WmiRelativeBlockOffSet t_BlockOffSet = sizeof ( WmiBPKeyNode ) ; t_BlockOffSet = t_BlockOffSet + t_NodeStart * t_InternalKeySize + a_NodeIndex * t_InternalKeySize ; if ( t_Leaf ) { if ( a_NodeIndex < t_NodeSize ) { a_NodeOffSet = t_BlockOffSet ; a_ChildOffSet = 0 ; } else { t_StatusCode = e_StatusCode_NotFound ; } } else { if ( a_NodeIndex <= t_NodeSize ) { CopyMemory ( ( BYTE * ) & a_ChildOffSet , ( ( BYTE * ) ( a_Node ) ) + t_BlockOffSet + WmiBlockKeyPointerOffSet , sizeof ( WmiAbsoluteBlockOffSet ) ) ; if ( a_NodeIndex < t_NodeSize ) { a_NodeOffSet = t_BlockOffSet ; } else { a_NodeOffSet = 0 ; } } else { t_StatusCode = e_StatusCode_NotFound ; } } return t_StatusCode ; } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ WmiStatusCode WmiBPlusTree :: GetKeyElement ( WmiBPKeyNode *a_Node , const WmiAbsoluteBlockOffSet &a_BlockOffSet , const ULONG &a_NodeIndex , Iterator &a_Iterator ) { ULONG t_InternalKeySize = GetKeyTypeLength () ; BOOL t_Leaf = ( ( a_Node->GetFlags () & WMIBPLUS_TREE_FLAG_LEAF ) == WMIBPLUS_TREE_FLAG_LEAF ) ; if ( t_Leaf ) { t_InternalKeySize = t_InternalKeySize + WmiBlockLeafKeyOffSet ; } else { t_InternalKeySize = t_InternalKeySize + WmiBlockKeyOffSet ; } ULONG t_NodeStart = a_Node->GetNodeStart () ; ULONG t_NodeSize = a_Node->GetNodeSize () ; WmiRelativeBlockOffSet t_BlockOffSet = sizeof ( WmiBPKeyNode ) ; t_BlockOffSet = t_BlockOffSet + t_NodeStart * t_InternalKeySize + a_NodeIndex * t_InternalKeySize ; if ( t_Leaf ) { CopyMemory ( ( BYTE * ) & a_Iterator.GetElement () , ( ( BYTE * ) ( a_Node ) ) + t_BlockOffSet + WmiBlockLeafKeyElementOffSet , sizeof ( WmiAbsoluteBlockOffSet ) ) ; CopyMemory ( ( BYTE * ) a_Iterator.GetKey ().GetData () , ( ( BYTE * ) ( a_Node ) ) + t_BlockOffSet + WmiBlockLeafKeyOffSet , GetKeyTypeLength () ) ; } else { CopyMemory ( ( BYTE * ) & a_Iterator.GetElement () , ( ( BYTE * ) ( a_Node ) ) + t_BlockOffSet + WmiBlockKeyElementOffSet , sizeof ( WmiAbsoluteBlockOffSet ) ) ; CopyMemory ( ( BYTE * ) a_Iterator.GetKey ().GetData () , ( ( BYTE * ) ( a_Node ) ) + t_BlockOffSet + WmiBlockKeyOffSet , GetKeyTypeLength () ) ; } return e_StatusCode_Success ; } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ WmiStatusCode WmiBPlusTree :: LeftMost ( Iterator &a_Iterator ) { WmiStack &t_Stack = a_Iterator.GetStack () ; ULONG t_NodeIndex = a_Iterator.GetNodeIndex () ; WmiAbsoluteBlockOffSet t_BlockOffSet = a_Iterator.GetNodeOffSet () ; WmiRelativeBlockOffSet t_NodeOffSet = 0 ; WmiAbsoluteBlockOffSet t_ChildOffSet = 0 ; WmiStatusCode t_StatusCode = e_StatusCode_Success ; do { BYTE *t_Block = NULL ; t_StatusCode = m_BlockAllocator.ReadBlock ( 1 , t_BlockOffSet , t_Block ) ; if ( t_StatusCode == e_StatusCode_Success ) { WmiBPKeyNode *t_Node = ( WmiBPKeyNode * ) t_Block ; t_StatusCode = PositionInBlock ( t_Node , t_BlockOffSet , t_NodeIndex , t_NodeOffSet , t_ChildOffSet ) ; if ( t_StatusCode == e_StatusCode_Success ) { if ( t_ChildOffSet ) { t_StatusCode = t_Stack.Push ( IteratorPosition ( t_BlockOffSet , t_NodeIndex ) ) ; } else { a_Iterator.SetNodeIndex ( t_NodeIndex ) ; a_Iterator.SetNodeOffSet ( t_BlockOffSet ) ; t_StatusCode = GetKeyElement ( t_Node , t_BlockOffSet , t_NodeIndex , a_Iterator ) ; } } m_BlockAllocator.ReleaseBlock ( t_Block ) ; t_NodeIndex = 0 ; t_BlockOffSet = t_ChildOffSet ; } } while ( ( t_StatusCode == e_StatusCode_Success ) && t_ChildOffSet ) ; return t_StatusCode ; } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ WmiStatusCode WmiBPlusTree :: RightMost ( Iterator &a_Iterator ) { WmiStack &t_Stack = a_Iterator.GetStack () ; ULONG t_NodeIndex = a_Iterator.GetNodeIndex () ; WmiAbsoluteBlockOffSet t_BlockOffSet = a_Iterator.GetNodeOffSet () ; WmiRelativeBlockOffSet t_NodeOffSet = 0 ; WmiAbsoluteBlockOffSet t_ChildOffSet = 0 ; WmiStatusCode t_StatusCode = e_StatusCode_Success ; do { BYTE *t_Block = NULL ; t_StatusCode = m_BlockAllocator.ReadBlock ( 1 , t_BlockOffSet , t_Block ) ; if ( t_StatusCode == e_StatusCode_Success ) { WmiBPKeyNode *t_Node = ( WmiBPKeyNode * ) t_Block ; BOOL t_Leaf = ( ( t_Node->GetFlags () & WMIBPLUS_TREE_FLAG_LEAF ) == WMIBPLUS_TREE_FLAG_LEAF ) ; if ( t_Leaf ) { t_NodeIndex = t_Node->GetNodeSize () - t_Node->GetNodeStart () - 1 ; } else { t_NodeIndex = t_Node->GetNodeSize () - t_Node->GetNodeStart () ; } t_StatusCode = PositionInBlock ( t_Node , t_BlockOffSet , t_NodeIndex , t_NodeOffSet , t_ChildOffSet ) ; if ( t_StatusCode == e_StatusCode_Success ) { if ( t_ChildOffSet ) { t_StatusCode = t_Stack.Push ( IteratorPosition ( t_BlockOffSet , t_NodeIndex ) ) ; } else { a_Iterator.SetNodeIndex ( t_NodeIndex ) ; a_Iterator.SetNodeOffSet ( t_BlockOffSet ) ; t_StatusCode = GetKeyElement ( t_Node , t_BlockOffSet , t_NodeIndex , a_Iterator ) ; } } t_NodeIndex = 0 ; t_BlockOffSet = t_ChildOffSet ; m_BlockAllocator.ReleaseBlock ( t_Block ) ; } } while ( ( t_StatusCode == e_StatusCode_Success ) && t_ChildOffSet ) ; return t_StatusCode ; } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ WmiStatusCode WmiBPlusTree :: Increment ( Iterator &a_Iterator ) { WmiStatusCode t_StatusCode = e_StatusCode_Success ; WmiStack &t_Stack = a_Iterator.GetStack () ; ULONG t_NodeIndex = a_Iterator.GetNodeIndex () ; WmiAbsoluteBlockOffSet t_BlockOffSet = a_Iterator.GetNodeOffSet () ; if ( t_BlockOffSet ) { BYTE *t_Block = NULL ; WmiStatusCode t_StatusCode = m_BlockAllocator.ReadBlock ( 1 , t_BlockOffSet , t_Block ) ; if ( t_StatusCode == e_StatusCode_Success ) { WmiBPKeyNode *t_Node = ( WmiBPKeyNode * ) t_Block ; t_NodeIndex ++ ; WmiAbsoluteBlockOffSet t_ChildOffSet = 0 ; WmiRelativeBlockOffSet t_NodeOffSet = 0 ; WmiStatusCode t_TempStatusCode = PositionInBlock ( t_Node , t_BlockOffSet , t_NodeIndex , t_NodeOffSet , t_ChildOffSet ) ; if ( t_TempStatusCode == e_StatusCode_Success ) { if ( t_ChildOffSet ) { t_StatusCode = t_Stack.Push ( IteratorPosition ( t_BlockOffSet , t_NodeIndex ) ) ; if ( t_StatusCode == e_StatusCode_Success ) { BYTE *t_Block = NULL ; t_StatusCode = m_BlockAllocator.ReadBlock ( 1 , t_ChildOffSet , t_Block ) ; if ( t_StatusCode == e_StatusCode_Success ) { WmiBPKeyNode *t_ChildNode = ( WmiBPKeyNode * ) t_Block ; a_Iterator.SetNodeOffSet ( t_ChildOffSet ) ; a_Iterator.SetNodeIndex ( t_ChildNode->GetNodeStart () ) ; t_StatusCode = LeftMost ( a_Iterator ) ; m_BlockAllocator.ReleaseBlock ( t_Block ) ; } } } else { a_Iterator.SetNodeIndex ( t_NodeIndex ) ; t_StatusCode = GetKeyElement ( t_Node , t_BlockOffSet , t_NodeIndex , a_Iterator ) ; } } else { IteratorPosition t_Position ; while ( ( t_TempStatusCode = t_Stack.Top ( t_Position ) ) == e_StatusCode_Success ) { t_Stack.Pop () ; BYTE *t_Block = NULL ; t_StatusCode = m_BlockAllocator.ReadBlock ( 1 , t_Position.GetNodeOffSet () , t_Block ) ; if ( t_StatusCode == e_StatusCode_Success ) { WmiBPKeyNode *t_ParentNode = ( WmiBPKeyNode * ) t_Block ; if ( t_Position.GetNodeIndex () < ( t_ParentNode->GetNodeSize () - t_ParentNode->GetNodeStart () ) ) { a_Iterator.SetNodeIndex ( t_Position.GetNodeIndex () ) ; a_Iterator.SetNodeOffSet ( t_Position.GetNodeOffSet () ) ; t_StatusCode = GetKeyElement ( t_ParentNode , t_Position.GetNodeOffSet () , t_Position.GetNodeIndex () , a_Iterator ) ; m_BlockAllocator.ReleaseBlock ( t_Block ) ; break ; } m_BlockAllocator.ReleaseBlock ( t_Block ) ; } } if ( t_TempStatusCode != e_StatusCode_Success ) { a_Iterator.SetNodeIndex ( 0 ) ; a_Iterator.SetNodeOffSet ( 0 ) ; } } m_BlockAllocator.ReleaseBlock ( t_Block ) ; } } else { t_StatusCode = e_StatusCode_Failed ; } return t_StatusCode ; } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ WmiStatusCode WmiBPlusTree :: Decrement ( Iterator &a_Iterator ) { WmiStatusCode t_StatusCode = e_StatusCode_Success ; WmiStack &t_Stack = a_Iterator.GetStack () ; ULONG t_NodeIndex = a_Iterator.GetNodeIndex () ; WmiAbsoluteBlockOffSet t_BlockOffSet = a_Iterator.GetNodeOffSet () ; if ( t_BlockOffSet ) { BYTE *t_Block = NULL ; WmiStatusCode t_StatusCode = m_BlockAllocator.ReadBlock ( 1 , t_BlockOffSet , t_Block ) ; if ( t_StatusCode == e_StatusCode_Success ) { WmiBPKeyNode *t_Node = ( WmiBPKeyNode * ) t_Block ; t_NodeIndex -- ; WmiAbsoluteBlockOffSet t_ChildOffSet = 0 ; WmiRelativeBlockOffSet t_NodeOffSet = 0 ; WmiStatusCode t_TempStatusCode = PositionInBlock ( t_Node , t_BlockOffSet , t_NodeIndex , t_NodeOffSet , t_ChildOffSet ) ; if ( t_TempStatusCode == e_StatusCode_Success ) { if ( t_ChildOffSet ) { t_StatusCode = t_Stack.Push ( IteratorPosition ( t_BlockOffSet , t_NodeIndex ) ) ; if ( t_StatusCode == e_StatusCode_Success ) { BYTE *t_Block = NULL ; t_StatusCode = m_BlockAllocator.ReadBlock ( 1 , t_ChildOffSet , t_Block ) ; if ( t_StatusCode == e_StatusCode_Success ) { WmiBPKeyNode *t_ChildNode = ( WmiBPKeyNode * ) t_Block ; a_Iterator.SetNodeOffSet ( t_ChildOffSet ) ; a_Iterator.SetNodeIndex ( t_ChildNode->GetNodeStart () + t_ChildNode->GetNodeSize () - 1 ) ; t_StatusCode = RightMost ( a_Iterator ) ; m_BlockAllocator.ReleaseBlock ( t_Block ) ; } } } else { a_Iterator.SetNodeIndex ( t_NodeIndex ) ; t_StatusCode = GetKeyElement ( t_Node , t_BlockOffSet , t_NodeIndex , a_Iterator ) ; } } else { IteratorPosition t_Position ; while ( ( t_TempStatusCode = t_Stack.Top ( t_Position ) ) == e_StatusCode_Success ) { t_Stack.Pop () ; BYTE *t_Block = NULL ; t_StatusCode = m_BlockAllocator.ReadBlock ( 1 , t_Position.GetNodeOffSet () , t_Block ) ; if ( t_StatusCode == e_StatusCode_Success ) { WmiBPKeyNode *t_ParentNode = ( WmiBPKeyNode * ) t_Block ; if ( t_Position.GetNodeIndex () > t_ParentNode->GetNodeStart () ) { a_Iterator.SetNodeIndex ( t_Position.GetNodeIndex () ) ; a_Iterator.SetNodeOffSet ( t_Position.GetNodeOffSet () ) ; t_StatusCode = GetKeyElement ( t_ParentNode , t_Position.GetNodeOffSet () , t_Position.GetNodeIndex () - 1 , a_Iterator ) ; m_BlockAllocator.ReleaseBlock ( t_Block ) ; break ; } m_BlockAllocator.ReleaseBlock ( t_Block ) ; } } if ( t_TempStatusCode != e_StatusCode_Success ) { a_Iterator.SetNodeIndex ( 0 ) ; a_Iterator.SetNodeOffSet ( 0 ) ; } } m_BlockAllocator.ReleaseBlock ( t_Block ) ; } } else { t_StatusCode = e_StatusCode_Failed ; } return t_StatusCode ; } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ WmiBPlusTree :: Iterator &WmiBPlusTree :: Begin ( Iterator &a_Iterator ) { if ( m_Root ) { BYTE *t_Block = NULL ; WmiStatusCode t_StatusCode = m_BlockAllocator.ReadBlock ( 1 , m_Root , t_Block ) ; if ( t_StatusCode == e_StatusCode_Success ) { WmiBPKeyNode *t_Node = ( WmiBPKeyNode * ) t_Block ; a_Iterator.SetNodeOffSet ( m_Root ) ; a_Iterator.SetNodeIndex ( t_Node->GetNodeStart () ) ; t_StatusCode = LeftMost ( a_Iterator ) ; if ( t_StatusCode != e_StatusCode_Success ) { a_Iterator.SetNodeOffSet ( 0 ) ; a_Iterator.SetNodeIndex ( 0 ) ; } } else { a_Iterator.SetNodeOffSet ( 0 ) ; a_Iterator.SetNodeIndex ( 0 ) ; } } else { a_Iterator.SetNodeOffSet ( 0 ) ; a_Iterator.SetNodeIndex ( 0 ) ; } return a_Iterator ; } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ WmiBPlusTree :: Iterator &WmiBPlusTree :: End ( Iterator &a_Iterator ) { if ( m_Root ) { BYTE *t_Block = NULL ; WmiStatusCode t_StatusCode = m_BlockAllocator.ReadBlock ( 1 , m_Root , t_Block ) ; if ( t_StatusCode == e_StatusCode_Success ) { WmiBPKeyNode *t_Node = ( WmiBPKeyNode * ) t_Block ; a_Iterator.SetNodeOffSet ( m_Root ) ; a_Iterator.SetNodeIndex ( t_Node->GetNodeStart () + t_Node->GetNodeSize () - 1 ) ; t_StatusCode = RightMost ( a_Iterator ) ; if ( t_StatusCode != e_StatusCode_Success ) { a_Iterator.SetNodeOffSet ( 0 ) ; a_Iterator.SetNodeIndex ( 0 ) ; } m_BlockAllocator.ReleaseBlock ( t_Block ) ; } else { a_Iterator.SetNodeOffSet ( 0 ) ; a_Iterator.SetNodeIndex ( 0 ) ; } } else { a_Iterator.SetNodeOffSet ( 0 ) ; a_Iterator.SetNodeIndex ( 0 ) ; } return a_Iterator ; } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ WmiBPlusTree :: Iterator &WmiBPlusTree :: Root ( Iterator &a_Iterator ) { if ( m_Root ) { BYTE *t_Block = NULL ; WmiStatusCode t_StatusCode = m_BlockAllocator.ReadBlock ( 1 , m_Root , t_Block ) ; if ( t_StatusCode == e_StatusCode_Success ) { WmiBPKeyNode *t_Node = ( WmiBPKeyNode * ) t_Block ; a_Iterator.SetNodeOffSet ( m_Root ) ; a_Iterator.SetNodeIndex ( t_Node->GetNodeStart () ) ; m_BlockAllocator.ReleaseBlock ( t_Block ) ; } else { a_Iterator.SetNodeOffSet ( 0 ) ; a_Iterator.SetNodeIndex ( 0 ) ; } } else { a_Iterator.SetNodeOffSet ( 0 ) ; a_Iterator.SetNodeIndex ( 0 ) ; } return a_Iterator ; } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ WmiStatusCode WmiBPlusTree :: FindInBlock ( WmiBPKeyNode *a_Node , WmiAbsoluteBlockOffSet &a_BlockOffSet , const WmiBPKey &a_Key , WmiAbsoluteBlockOffSet &a_ChildOffSet , WmiBPElement &a_Element , WmiRelativeBlockOffSet &a_NodeOffSet , ULONG &a_NodeIndex ) { WmiStatusCode t_StatusCode = e_StatusCode_Success ; #ifdef COMMON_DEBUG PrintNode ( L"\nFindInBlock" , a_Node , a_BlockOffSet ) ; #endif ULONG t_InternalKeySize = GetKeyTypeLength () ; ULONG t_KeyOffSet ; BOOL t_Leaf = ( ( a_Node->GetFlags () & WMIBPLUS_TREE_FLAG_LEAF ) == WMIBPLUS_TREE_FLAG_LEAF ) ; if ( t_Leaf ) { t_KeyOffSet = WmiBlockLeafKeyOffSet ; t_InternalKeySize = t_InternalKeySize + WmiBlockLeafKeyOffSet ; } else { t_KeyOffSet = WmiBlockKeyOffSet ; t_InternalKeySize = t_InternalKeySize + WmiBlockKeyOffSet ; } ULONG t_LowerIndex = a_Node->GetNodeStart () ; ULONG t_UpperIndex = a_Node->GetNodeSize () ; while ( t_LowerIndex < t_UpperIndex ) { ULONG t_Index = ( t_LowerIndex + t_UpperIndex ) >> 1 ; WmiAbsoluteBlockOffSet t_BlockOffSet = sizeof ( WmiBPKeyNode ) + ( t_Index * t_InternalKeySize ) ; BYTE *t_Buffer = ( ( BYTE * ) a_Node ) + t_BlockOffSet + t_KeyOffSet ; WmiBPKey t_Key ( t_Buffer , GetKeyTypeLength () ) ; LONG t_Compare = GetComparatorFunction () ( GetComparatorOperand () , a_Key , t_Key ) ; if ( t_Compare == 0 ) { if ( t_Leaf ) { CopyMemory ( ( BYTE * ) & a_Element , ( ( BYTE * ) ( a_Node ) ) + t_BlockOffSet + WmiBlockLeafKeyElementOffSet , sizeof ( WmiAbsoluteBlockOffSet ) ) ; a_NodeOffSet = t_BlockOffSet ; } else { CopyMemory ( ( BYTE * ) & a_Element , ( ( BYTE * ) ( a_Node ) ) + t_BlockOffSet + WmiBlockKeyElementOffSet , sizeof ( WmiAbsoluteBlockOffSet ) ) ; a_NodeOffSet = t_BlockOffSet ; } a_NodeIndex = t_Index ; return t_StatusCode ; } else { if ( t_Compare < 0 ) { t_UpperIndex = t_Index ; } else { t_LowerIndex = t_Index + 1 ; } } } if ( t_Leaf ) { t_StatusCode = e_StatusCode_NotFound ; } else { WmiAbsoluteBlockOffSet t_BlockOffSet = sizeof ( WmiBPKeyNode ) + ( t_UpperIndex * t_InternalKeySize ) ; CopyMemory ( ( BYTE * ) & a_ChildOffSet , ( ( BYTE * ) ( a_Node ) ) + t_BlockOffSet + WmiBlockKeyPointerOffSet , sizeof ( WmiAbsoluteBlockOffSet ) ) ; a_NodeIndex = t_UpperIndex ; } return t_StatusCode ; } #if 0 /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ WmiStatusCode WmiBPlusTree :: FindInBlock ( WmiBPKeyNode *a_Node , WmiAbsoluteBlockOffSet &a_BlockOffSet , const WmiBPKey &a_Key , WmiAbsoluteBlockOffSet &a_ChildOffSet , WmiBPElement &a_Element , WmiRelativeBlockOffSet &a_NodeOffSet , ULONG &a_NodeIndex ) { WmiStatusCode t_StatusCode = e_StatusCode_Success ; #ifdef COMMON_DEBUG PrintNode ( L"\nFindInBlock" , a_Node , a_BlockOffSet ) ; #endif WmiAbsoluteBlockOffSet t_BlockOffSet = sizeof ( WmiBPKeyNode ) ; ULONG t_InternalKeySize = GetKeyTypeLength () ; ULONG t_KeyOffSet ; BOOL t_Leaf = ( ( a_Node->GetFlags () & WMIBPLUS_TREE_FLAG_LEAF ) == WMIBPLUS_TREE_FLAG_LEAF ) ; if ( t_Leaf ) { t_KeyOffSet = WmiBlockLeafKeyOffSet ; t_InternalKeySize = t_InternalKeySize + WmiBlockLeafKeyOffSet ; } else { t_KeyOffSet = WmiBlockKeyOffSet ; t_InternalKeySize = t_InternalKeySize + WmiBlockKeyOffSet ; } ULONG t_NodeStart = a_Node->GetNodeStart () ; ULONG t_NodeSize = a_Node->GetNodeSize () ; for ( ULONG t_Index = t_NodeStart ; t_Index < t_NodeSize ; t_Index ++ ) { BYTE *t_Buffer = ( ( BYTE * ) a_Node ) + t_BlockOffSet + t_KeyOffSet ; WmiBPKey t_Key ( t_Buffer , GetKeyTypeLength () ) ; LONG t_Compare = GetComparatorFunction () ( GetComparatorOperand () , a_Key , t_Key ) ; if ( t_Compare == 0 ) { if ( t_Leaf ) { CopyMemory ( ( BYTE * ) & a_Element , ( ( BYTE * ) ( a_Node ) ) + t_BlockOffSet + WmiBlockLeafKeyElementOffSet , sizeof ( WmiAbsoluteBlockOffSet ) ) ; a_NodeOffSet = t_BlockOffSet ; } else { CopyMemory ( ( BYTE * ) & a_Element , ( ( BYTE * ) ( a_Node ) ) + t_BlockOffSet + WmiBlockKeyElementOffSet , sizeof ( WmiAbsoluteBlockOffSet ) ) ; a_NodeOffSet = t_BlockOffSet ; } a_NodeIndex = t_Index ; return t_StatusCode ; } else if ( t_Compare < 0 ) { if ( t_Leaf ) { t_StatusCode = e_StatusCode_NotFound ; } else { CopyMemory ( ( BYTE * ) & a_ChildOffSet , ( ( BYTE * ) ( a_Node ) ) + t_BlockOffSet + WmiBlockKeyPointerOffSet , sizeof ( WmiAbsoluteBlockOffSet ) ) ; a_NodeIndex = t_Index ; } return t_StatusCode ; } t_BlockOffSet = t_BlockOffSet + t_InternalKeySize ; } if ( t_Leaf ) { t_StatusCode = e_StatusCode_NotFound ; } else { CopyMemory ( ( BYTE * ) & a_ChildOffSet , ( ( BYTE * ) ( a_Node ) ) + t_BlockOffSet + WmiBlockKeyPointerOffSet , sizeof ( WmiAbsoluteBlockOffSet ) ) ; a_NodeIndex = t_Index ; } return t_StatusCode ; } #endif /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ WmiStatusCode WmiBPlusTree :: Find ( const WmiBPKey &a_Key , Iterator &a_Iterator ) { WmiStatusCode t_StatusCode = e_StatusCode_Success ; if ( m_Root ) { t_StatusCode = RecursiveFind ( m_Root , a_Key , a_Iterator ) ; } else { return e_StatusCode_NotFound ; } return t_StatusCode ; } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ WmiStatusCode WmiBPlusTree :: RecursiveFind ( WmiAbsoluteBlockOffSet &a_BlockOffSet , const WmiBPKey &a_Key , Iterator &a_Iterator ) { WmiAbsoluteBlockOffSet t_ChildOffSet = 0 ; WmiBPElement t_Element = 0 ; BYTE *t_Block = NULL ; WmiStatusCode t_StatusCode = m_BlockAllocator.ReadBlock ( 1 , a_BlockOffSet , t_Block ) ; if ( t_StatusCode == e_StatusCode_Success ) { WmiBPKeyNode *t_Node = ( WmiBPKeyNode * ) t_Block ; WmiRelativeBlockOffSet t_NodeOffSet = 0 ; ULONG t_NodeIndex = 0 ; t_StatusCode = FindInBlock ( t_Node , a_BlockOffSet , a_Key , t_ChildOffSet , t_Element , t_NodeOffSet , t_NodeIndex ) ; if ( t_StatusCode == e_StatusCode_Success ) { if ( t_ChildOffSet ) { WmiStack &t_Stack = a_Iterator.GetStack () ; t_StatusCode = t_Stack.Push ( IteratorPosition ( a_BlockOffSet , t_NodeIndex ) ) ; if ( t_StatusCode == e_StatusCode_Success ) { t_StatusCode = RecursiveFind ( t_ChildOffSet , a_Key , a_Iterator ) ; } } else { a_Iterator.SetNodeOffSet ( a_BlockOffSet ) ; a_Iterator.SetNodeIndex ( t_NodeIndex ) ; a_Iterator.GetElement () = t_Element ; CopyMemory ( a_Iterator.GetKey ().GetData () , a_Key.GetConstData () , GetKeyTypeLength () ) ; } } m_BlockAllocator.ReleaseBlock ( t_Block ) ; } return t_StatusCode ; } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ WmiStatusCode WmiBPlusTree :: SetLeafNode ( WmiBPKeyNode *a_Node , const WmiRelativeBlockOffSet &a_NodeDeltaOffSet , const WmiBPKey &a_Key , const WmiBPElement &a_Element ) { WmiStatusCode t_StatusCode = e_StatusCode_Success ; BYTE *t_Buffer = ( ( BYTE * ) a_Node ) + a_NodeDeltaOffSet + WmiBlockLeafKeyOffSet ; CopyMemory ( t_Buffer , ( BYTE * ) a_Key.GetConstData () , a_Key.GetConstDataSize () , ) ; t_Buffer = ( ( BYTE * ) a_Node ) + a_NodeDeltaOffSet + WmiBlockLeafKeyElementOffSet ; CopyMemory ( t_Buffer , ( BYTE * ) & ( a_Element ) , sizeof ( a_Element ) ) ; return t_StatusCode ; } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ WmiStatusCode WmiBPlusTree :: SetNode ( WmiBPKeyNode *a_Node , const WmiRelativeBlockOffSet &a_NodeDeltaOffSet , const WmiBPKey &a_Key , const WmiBPElement &a_Element , WmiAbsoluteBlockOffSet &a_LeftCutBlockOffSet , WmiAbsoluteBlockOffSet &a_RightCutBlockOffSet ) { WmiStatusCode t_StatusCode = e_StatusCode_Success ; BYTE *t_Buffer = ( ( BYTE * ) a_Node ) + a_NodeDeltaOffSet + WmiBlockKeyOffSet ; CopyMemory ( t_Buffer , ( BYTE * ) a_Key.GetConstData () , a_Key.GetConstDataSize () , ) ; t_Buffer = ( ( BYTE * ) a_Node ) + a_NodeDeltaOffSet + WmiBlockKeyElementOffSet ; CopyMemory ( t_Buffer , ( BYTE * ) & ( a_Element ) , sizeof ( a_Element ) ) ; t_Buffer = ( ( BYTE * ) a_Node ) + a_NodeDeltaOffSet + WmiBlockKeyPointerOffSet ; CopyMemory ( t_Buffer , ( BYTE * ) & ( a_LeftCutBlockOffSet ) , sizeof ( WmiAbsoluteBlockOffSet ) ) ; t_Buffer = ( ( BYTE * ) a_Node ) + a_NodeDeltaOffSet + WmiBlockKeyOffSet + a_Key.GetConstDataSize () + WmiBlockKeyPointerOffSet ; CopyMemory ( t_Buffer , ( BYTE * ) & ( a_RightCutBlockOffSet ) , sizeof ( WmiAbsoluteBlockOffSet ) ) ; return t_StatusCode ; } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ WmiStatusCode WmiBPlusTree :: PerformInsertion ( WmiBPKeyNode *a_Node , WmiAbsoluteBlockOffSet &a_BlockOffSet , const WmiBPKey &a_Key , WmiBPElement &a_Element , WmiBPKey &a_ReBalanceKey , WmiBPElement &a_ReBalanceElement , WmiAbsoluteBlockOffSet &a_LeftCutBlockOffSet , WmiAbsoluteBlockOffSet &a_RightCutBlockOffSet , WmiRelativeBlockOffSet &a_PositionBlockOffSet ) { WmiStatusCode t_StatusCode = e_StatusCode_Success ; #ifdef INSERT_DEBUG OutputDebugString ( L"\n/**************************************" ) ; wchar_t t_StringBuffer [ 1024 ] ; swprintf ( t_StringBuffer , L"\nInsertion Key = %I64x" , * ( UINT64 * ) a_Key.GetConstData () ) ; OutputDebugString ( t_StringBuffer ) ; #endif WmiRelativeBlockOffSet t_StartBlockOffSet = sizeof ( WmiBPKeyNode ) ; BOOL t_ReBalance ; ULONG t_PartitionPoint ; WmiRelativeBlockOffSet t_KeyOffSet ; WmiRelativeBlockOffSet t_KeyElementOffSet ; WmiRelativeBlockOffSet t_KeyPosition ; WmiRelativeBlockOffSet t_KeyPositionIncrement ; BOOL t_Leaf = ( ( a_Node->GetFlags () & WMIBPLUS_TREE_FLAG_LEAF ) == WMIBPLUS_TREE_FLAG_LEAF ) ; if ( t_Leaf ) { t_KeyPositionIncrement = WmiBlockLeafKeyOffSet + GetKeyTypeLength () ; t_ReBalance = ( a_Node->GetNodeSize () >= MaxLeafKeys () ) ? TRUE : FALSE ; if ( t_ReBalance ) { t_PartitionPoint = MaxLeafKeys () >> 1 ; t_KeyPosition = t_StartBlockOffSet + ( t_PartitionPoint * t_KeyPositionIncrement ) ; t_KeyOffSet = t_KeyPosition + WmiBlockLeafKeyOffSet ; t_KeyElementOffSet = t_KeyPosition + WmiBlockLeafKeyElementOffSet ; } } else { t_KeyPositionIncrement = WmiBlockKeyOffSet + GetKeyTypeLength () ; t_ReBalance = ( a_Node->GetNodeSize () >= MaxKeys () ) ? TRUE : FALSE ; if ( t_ReBalance ) { t_PartitionPoint = MaxKeys () >> 1 ; t_KeyPosition = t_StartBlockOffSet + ( t_PartitionPoint * t_KeyPositionIncrement ) ; t_KeyOffSet = t_KeyPosition + WmiBlockKeyOffSet ; t_KeyElementOffSet = t_KeyPosition + WmiBlockKeyElementOffSet; } } if ( t_ReBalance ) { BYTE *t_PartitionData = NULL ; t_StatusCode = m_Allocator.New ( ( void ** ) & t_PartitionData , GetKeyTypeLength () ) ; if ( t_StatusCode == e_StatusCode_Success ) { WmiAbsoluteBlockOffSet t_BlockOffSet = 0 ; BYTE *t_Block = NULL ; WmiStatusCode t_StatusCode = m_BlockAllocator.AllocateBlock ( 1 , t_BlockOffSet , t_Block ) ; if ( t_StatusCode == e_StatusCode_Success ) { WmiBPKeyNode *t_Node = ( WmiBPKeyNode * ) t_Block ; #ifdef INSERT_DEBUG PrintNode ( L"\nPre Re Balanced a_Node" , a_Node , a_BlockOffSet ) ; PrintNode ( L"\nPre Re Balanced t_Node" , t_Node , t_BlockOffSet ) ; #endif if ( a_PositionBlockOffSet < t_KeyPosition ) { /* * Copy key to trickle up. */ BYTE *t_Buffer = ( ( BYTE * ) a_Node ) + t_KeyOffSet - t_KeyPositionIncrement ; CopyMemory ( ( BYTE * ) t_PartitionData , t_Buffer , GetKeyTypeLength () , ) ; a_ReBalanceKey = WmiBPKey ( t_PartitionData , GetKeyTypeLength () , TRUE ) ; t_Buffer = ( ( BYTE * ) a_Node ) + t_KeyElementOffSet - t_KeyPositionIncrement ; CopyMemory ( ( BYTE * ) & ( a_ReBalanceElement ) , t_Buffer , sizeof ( a_ReBalanceElement ) ) ; t_Node->SetNodeSize ( t_PartitionPoint ) ; t_Node->SetNodeOffSet ( t_BlockOffSet ) ; t_Node->SetNodeStart ( 0 ) ; a_Node->SetNodeSize ( t_PartitionPoint ) ; /* * Copy Right partition to new node */ CopyMemory ( ( ( BYTE * ) t_Node ) + t_StartBlockOffSet , ( ( BYTE * ) a_Node ) + t_KeyPosition , ( ULONG ) ( t_PartitionPoint * t_KeyPositionIncrement ) + ( t_Leaf ? 0 : t_KeyPositionIncrement ) ) ; /* * Shuffle memory for key insertion */ WmiRelativeBlockOffSet t_TotalSize = t_StartBlockOffSet + a_Node->GetNodeSize () * t_KeyPositionIncrement ; WmiRelativeBlockOffSet t_MoveSize = t_TotalSize - a_PositionBlockOffSet ; MoveMemory ( ( ( BYTE * ) a_Node ) + a_PositionBlockOffSet + t_KeyPositionIncrement , ( ( BYTE * ) a_Node ) + a_PositionBlockOffSet , ( ULONG ) t_MoveSize + ( t_Leaf ? 0 : t_KeyPositionIncrement ) ) ; if ( t_Leaf ) { t_StatusCode = SetLeafNode ( a_Node , a_PositionBlockOffSet , a_Key , a_Element ) ; t_Node->SetFlags ( WMIBPLUS_TREE_FLAG_LEAF ) ; } else { t_StatusCode = SetNode ( a_Node , a_PositionBlockOffSet , a_Key , a_Element , a_LeftCutBlockOffSet , a_RightCutBlockOffSet ) ; t_Node->SetFlags ( WMIBPLUS_TREE_FLAG_INTERNAL ) ; } t_StatusCode = m_BlockAllocator.WriteBlock ( ( BYTE * ) & a_Node ) ; if ( t_StatusCode == e_StatusCode_Success ) { t_StatusCode = m_BlockAllocator.WriteBlock ( ( BYTE * ) & t_Node ) ; if ( t_StatusCode == e_StatusCode_Success ) { a_LeftCutBlockOffSet = a_BlockOffSet ; a_RightCutBlockOffSet = t_BlockOffSet ; } } } else if ( a_PositionBlockOffSet > t_KeyPosition ) { /* * Copy key to trickle up. */ BYTE *t_Buffer = ( ( BYTE * ) a_Node ) + t_KeyOffSet ; CopyMemory ( ( BYTE * ) t_PartitionData , t_Buffer , GetKeyTypeLength () , ) ; a_ReBalanceKey = WmiBPKey ( t_PartitionData , GetKeyTypeLength () , TRUE ) ; t_Buffer = ( ( BYTE * ) a_Node ) + t_KeyElementOffSet ; CopyMemory ( ( BYTE * ) & ( a_ReBalanceElement ) , t_Buffer , sizeof ( a_ReBalanceElement ) ) ; t_Node->SetNodeSize ( t_PartitionPoint ) ; t_Node->SetNodeOffSet ( t_BlockOffSet ) ; t_Node->SetNodeStart ( 0 ) ; a_Node->SetNodeSize ( t_PartitionPoint ) ; CopyMemory ( ( ( BYTE * ) t_Node ) + t_StartBlockOffSet , ( ( BYTE * ) a_Node ) + t_KeyPosition + t_KeyPositionIncrement , ( ULONG ) ( ( t_PartitionPoint - 1 ) * t_KeyPositionIncrement ) + ( t_Leaf ? 0 : t_KeyPositionIncrement ) ) ; WmiRelativeBlockOffSet t_TotalSize = t_StartBlockOffSet + t_Node->GetNodeSize () * t_KeyPositionIncrement ; WmiRelativeBlockOffSet t_MoveSize = t_TotalSize - ( t_StartBlockOffSet + a_PositionBlockOffSet - t_KeyPosition ) ; MoveMemory ( ( ( BYTE * ) t_Node ) + ( t_StartBlockOffSet + a_PositionBlockOffSet - t_KeyPosition ) , ( ( BYTE * ) t_Node ) + ( t_StartBlockOffSet + a_PositionBlockOffSet - t_KeyPosition ) - t_KeyPositionIncrement , ( ULONG ) t_MoveSize + ( t_Leaf ? 0 : t_KeyPositionIncrement ) ) ; if ( t_Leaf ) { t_StatusCode = SetLeafNode ( t_Node , ( t_StartBlockOffSet + a_PositionBlockOffSet - ( t_KeyPosition ) ) - t_KeyPositionIncrement , a_Key , a_Element ) ; t_Node->SetFlags ( WMIBPLUS_TREE_FLAG_LEAF ) ; } else { t_StatusCode = SetNode ( t_Node , ( t_StartBlockOffSet + a_PositionBlockOffSet - ( t_KeyPosition ) ) - t_KeyPositionIncrement , a_Key , a_Element , a_LeftCutBlockOffSet , a_RightCutBlockOffSet ) ; t_Node->SetFlags ( WMIBPLUS_TREE_FLAG_INTERNAL ) ; } t_StatusCode = m_BlockAllocator.WriteBlock ( ( BYTE * ) & a_Node ) ; if ( t_StatusCode == e_StatusCode_Success ) { t_StatusCode = m_BlockAllocator.WriteBlock ( ( BYTE * ) & t_Node ) ; if ( t_StatusCode == e_StatusCode_Success ) { a_LeftCutBlockOffSet = a_BlockOffSet ; a_RightCutBlockOffSet = t_BlockOffSet ; } } } else { /* * Copy key to trickle up. */ BYTE *t_Buffer = ( ( BYTE * ) a_Node ) + t_KeyOffSet ; CopyMemory ( ( BYTE * ) t_PartitionData , t_Buffer , GetKeyTypeLength () , ) ; WmiBPKey t_TempKey = WmiBPKey ( t_PartitionData , GetKeyTypeLength () , TRUE ) ; WmiBPElement t_TempElement ; t_Buffer = ( ( BYTE * ) a_Node ) + t_KeyElementOffSet ; CopyMemory ( ( BYTE * ) & ( t_TempElement ) , t_Buffer , sizeof ( t_TempElement ) ) ; a_ReBalanceKey = t_TempKey ; a_ReBalanceElement = t_TempElement ; t_Node->SetNodeSize ( t_PartitionPoint ) ; t_Node->SetNodeOffSet ( t_BlockOffSet ) ; t_Node->SetNodeStart ( 0 ) ; a_Node->SetNodeSize ( t_PartitionPoint ) ; CopyMemory ( ( ( BYTE * ) t_Node ) + t_StartBlockOffSet , ( ( BYTE * ) a_Node ) + t_KeyPosition + t_KeyPositionIncrement , ( ULONG ) ( ( t_PartitionPoint - 1 ) * t_KeyPositionIncrement ) + ( t_Leaf ? 0 : t_KeyPositionIncrement ) ) ; WmiAbsoluteBlockOffSet t_LeftPointerBlockOffSet = 0 ; CopyMemory ( ( BYTE * ) & t_LeftPointerBlockOffSet , ( ( BYTE * ) t_Node ) + ( t_StartBlockOffSet + a_PositionBlockOffSet - ( t_KeyPosition ) ) , sizeof ( WmiAbsoluteBlockOffSet ) ) ; WmiAbsoluteBlockOffSet t_RightPointerBlockOffSet = 0 ; CopyMemory ( ( BYTE * ) & t_RightPointerBlockOffSet , ( ( BYTE * ) t_Node ) + ( t_StartBlockOffSet + a_PositionBlockOffSet - ( t_KeyPosition ) ) + t_KeyPositionIncrement , sizeof ( WmiAbsoluteBlockOffSet ) ) ; WmiRelativeBlockOffSet t_TotalSize = t_StartBlockOffSet + t_Node->GetNodeSize () * t_KeyPositionIncrement ; WmiRelativeBlockOffSet t_MoveSize = t_TotalSize - ( t_StartBlockOffSet + a_PositionBlockOffSet - t_KeyPosition ) ; MoveMemory ( ( ( BYTE * ) t_Node ) + ( t_StartBlockOffSet + a_PositionBlockOffSet - t_KeyPosition ) + t_KeyPositionIncrement , ( ( BYTE * ) t_Node ) + ( t_StartBlockOffSet + a_PositionBlockOffSet - t_KeyPosition ) , ( ULONG ) t_MoveSize + ( t_Leaf ? 0 : t_KeyPositionIncrement ) ) ; LONG t_Compare = GetComparatorFunction () ( GetComparatorOperand () , a_Key , t_TempKey ) ; if ( t_Leaf ) { if ( t_Compare < 0 ) { t_StatusCode = SetLeafNode ( t_Node , ( t_StartBlockOffSet + a_PositionBlockOffSet - ( t_KeyPosition ) ) , t_TempKey , t_TempElement ) ; CopyMemory ( ( BYTE * ) t_PartitionData , a_Key.GetConstData () , GetKeyTypeLength () , ) ; CopyMemory ( ( BYTE * ) & ( a_ReBalanceElement ) , ( BYTE * ) & a_Element , sizeof ( a_ReBalanceElement ) ) ; } else { t_StatusCode = SetLeafNode ( t_Node , ( t_StartBlockOffSet + a_PositionBlockOffSet - ( t_KeyPosition ) ) , a_Key , a_Element ) ; } t_Node->SetFlags ( WMIBPLUS_TREE_FLAG_LEAF ) ; } else { if ( t_Compare < 0 ) { t_StatusCode = SetNode ( t_Node , ( t_StartBlockOffSet + a_PositionBlockOffSet - ( t_KeyPosition ) ) , t_TempKey , t_TempElement , a_RightCutBlockOffSet , t_LeftPointerBlockOffSet ) ; CopyMemory ( ( BYTE * ) t_PartitionData , a_Key.GetConstData () , GetKeyTypeLength () , ) ; CopyMemory ( ( BYTE * ) & ( a_ReBalanceElement ) , ( BYTE * ) & a_Element , sizeof ( a_ReBalanceElement ) ) ; a_RightCutBlockOffSet = t_BlockOffSet ; } else { t_StatusCode = SetNode ( t_Node , ( t_StartBlockOffSet + a_PositionBlockOffSet - ( t_KeyPosition ) ) , a_Key , a_Element , a_RightCutBlockOffSet , t_RightPointerBlockOffSet ) ; a_RightCutBlockOffSet = a_BlockOffSet ; } t_Node->SetFlags ( WMIBPLUS_TREE_FLAG_INTERNAL ) ; } t_StatusCode = m_BlockAllocator.WriteBlock ( ( BYTE * ) & a_Node ) ; if ( t_StatusCode == e_StatusCode_Success ) { t_StatusCode = m_BlockAllocator.WriteBlock ( ( BYTE * ) & t_Node ) ; if ( t_StatusCode == e_StatusCode_Success ) { a_LeftCutBlockOffSet = a_BlockOffSet ; a_RightCutBlockOffSet = t_BlockOffSet ; } } } #ifdef INSERT_DEBUG OutputDebugString ( L"\n/**************************************" ) ; wchar_t t_StringBuffer [ 1024 ] ; swprintf ( t_StringBuffer , L"\nReBalance Key = %I64x" , * ( UINT64 * ) a_ReBalanceKey.GetConstData () ) ; OutputDebugString ( t_StringBuffer ) ; PrintNode ( L"\nRe Balanced a_Node" , a_Node , a_BlockOffSet ) ; PrintNode ( L"\nRe Balanced t_Node" , t_Node , t_BlockOffSet ) ; #endif } } } else { /* * Shuffle memory for insertion */ #ifdef INSERT_DEBUG PrintNode ( L"\nPre Shuffled a_Node" , a_Node , a_BlockOffSet ) ; #endif WmiRelativeBlockOffSet t_TotalSize = t_StartBlockOffSet + a_Node->GetNodeSize () * t_KeyPositionIncrement ; WmiRelativeBlockOffSet t_MoveSize = t_TotalSize - a_PositionBlockOffSet ; MoveMemory ( ( ( BYTE * ) a_Node ) + a_PositionBlockOffSet + t_KeyPositionIncrement , ( ( BYTE * ) a_Node ) + a_PositionBlockOffSet , ( ULONG ) t_MoveSize + ( t_Leaf ? 0 : t_KeyPositionIncrement ) ) ; if ( t_Leaf ) { t_StatusCode = SetLeafNode ( a_Node , a_PositionBlockOffSet , a_Key , a_Element ) ; } else { t_StatusCode = SetNode ( a_Node , a_PositionBlockOffSet , a_Key , a_Element , a_LeftCutBlockOffSet , a_RightCutBlockOffSet ) ; } a_Node->SetNodeSize ( a_Node->GetNodeSize () + 1 ) ; #ifdef INSERT_DEBUG PrintNode ( L"\nShuffled a_Node" , a_Node , a_BlockOffSet ) ; #endif t_StatusCode = m_BlockAllocator.WriteBlock ( ( BYTE * ) & a_Node ) ; a_ReBalanceElement = 0 ; a_LeftCutBlockOffSet = 0 ; a_RightCutBlockOffSet = 0 ; } return t_StatusCode ; } #if 1 /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ WmiStatusCode WmiBPlusTree :: InsertInBlock ( WmiBPKeyNode *a_Node , WmiAbsoluteBlockOffSet &a_BlockOffSet , const WmiBPKey &a_Key , WmiBPElement &a_Element , WmiBPKey &a_ReBalanceKey , WmiBPElement &a_ReBalanceElement , WmiAbsoluteBlockOffSet &a_LeftCutBlockOffSet , WmiAbsoluteBlockOffSet &a_RightCutBlockOffSet ) { WmiStatusCode t_StatusCode = e_StatusCode_Success ; ULONG t_InternalKeySize = GetKeyTypeLength () ; ULONG t_KeyOffSet ; BOOL t_Leaf = ( ( a_Node->GetFlags () & WMIBPLUS_TREE_FLAG_LEAF ) == WMIBPLUS_TREE_FLAG_LEAF ) ; if ( t_Leaf ) { t_KeyOffSet = WmiBlockLeafKeyOffSet ; t_InternalKeySize = t_InternalKeySize + WmiBlockLeafKeyOffSet ; } else { t_KeyOffSet = WmiBlockKeyOffSet ; t_InternalKeySize = t_InternalKeySize + WmiBlockKeyOffSet ; } ULONG t_LowerIndex = a_Node->GetNodeStart () ; ULONG t_UpperIndex = a_Node->GetNodeSize () ; while ( t_LowerIndex < t_UpperIndex ) { ULONG t_Index = ( t_LowerIndex + t_UpperIndex ) >> 1 ; WmiAbsoluteBlockOffSet t_BlockOffSet = sizeof ( WmiBPKeyNode ) + ( t_Index * t_InternalKeySize ) ; WmiBPKey t_Key ( ( ( BYTE * ) a_Node ) + t_BlockOffSet + t_KeyOffSet , GetKeyTypeLength () ) ; LONG t_Compare = GetComparatorFunction () ( GetComparatorOperand () , a_Key , t_Key ) ; if ( t_Compare == 0 ) { /* * Can not happen at this juncture */ return e_StatusCode_AlreadyExists ; } else { if ( t_Compare < 0 ) { t_UpperIndex = t_Index ; } else { t_LowerIndex = t_Index + 1 ; } } } WmiAbsoluteBlockOffSet t_BlockOffSet = sizeof ( WmiBPKeyNode ) + ( t_UpperIndex * t_InternalKeySize ) ; t_StatusCode = PerformInsertion ( a_Node , a_BlockOffSet , a_Key , a_Element , a_ReBalanceKey , a_ReBalanceElement , a_LeftCutBlockOffSet , a_RightCutBlockOffSet , t_BlockOffSet ) ; return t_StatusCode ; } #else /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ WmiStatusCode WmiBPlusTree :: InsertInBlock ( WmiBPKeyNode *a_Node , WmiAbsoluteBlockOffSet &a_BlockOffSet , const WmiBPKey &a_Key , WmiBPElement &a_Element , WmiBPKey &a_ReBalanceKey , WmiBPElement &a_ReBalanceElement , WmiAbsoluteBlockOffSet &a_LeftCutBlockOffSet , WmiAbsoluteBlockOffSet &a_RightCutBlockOffSet ) { WmiStatusCode t_StatusCode = e_StatusCode_Success ; ULONG t_InternalKeySize = GetKeyTypeLength () ; ULONG t_KeyOffSet ; BOOL t_Leaf = ( ( a_Node->GetFlags () & WMIBPLUS_TREE_FLAG_LEAF ) == WMIBPLUS_TREE_FLAG_LEAF ) ; if ( t_Leaf ) { t_KeyOffSet = WmiBlockLeafKeyOffSet ; t_InternalKeySize = t_InternalKeySize + WmiBlockLeafKeyOffSet ; } else { t_KeyOffSet = WmiBlockKeyOffSet ; t_InternalKeySize = t_InternalKeySize + WmiBlockKeyOffSet ; } ULONG t_NodeStart = a_Node->GetNodeStart () ; ULONG t_NodeSize = a_Node->GetNodeSize () ; WmiAbsoluteBlockOffSet t_BlockOffSet = sizeof ( WmiBPKeyNode ) ; for ( ULONG t_Index = t_NodeStart ; t_Index < t_NodeSize ; t_Index ++ ) { WmiBPKey t_Key ( ( ( BYTE * ) a_Node ) + t_BlockOffSet + t_KeyOffSet , GetKeyTypeLength () ) ; LONG t_Compare = GetComparatorFunction () ( GetComparatorOperand () , a_Key , t_Key ) ; if ( t_Compare == 0 ) { /* * Can not happen at this juncture */ return e_StatusCode_AlreadyExists ; } else if ( t_Compare < 0 ) { /* * Found slot position to insert at. */ t_StatusCode = PerformInsertion ( a_Node , a_BlockOffSet , a_Key , a_Element , a_ReBalanceKey , a_ReBalanceElement , a_LeftCutBlockOffSet , a_RightCutBlockOffSet , t_BlockOffSet ) ; return t_StatusCode ; } t_BlockOffSet = t_BlockOffSet + t_InternalKeySize ; } /* * Found slot at end */ t_StatusCode = PerformInsertion ( a_Node , a_BlockOffSet , a_Key , a_Element , a_ReBalanceKey , a_ReBalanceElement , a_LeftCutBlockOffSet , a_RightCutBlockOffSet , t_BlockOffSet ) ; return t_StatusCode ; } #endif /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ WmiStatusCode WmiBPlusTree :: RecursiveInsert ( WmiStack &a_Stack , WmiAbsoluteBlockOffSet &a_BlockOffSet , const WmiBPKey &a_Key , const WmiBPElement &a_Element ) { WmiAbsoluteBlockOffSet t_ChildOffSet = 0 ; WmiBPElement t_Element = 0 ; BYTE *t_Block = NULL ; WmiStatusCode t_StatusCode = m_BlockAllocator.ReadBlock ( 1 , a_BlockOffSet , t_Block ) ; if ( t_StatusCode == e_StatusCode_Success ) { WmiBPKeyNode *t_Node = ( WmiBPKeyNode * ) t_Block ; WmiRelativeBlockOffSet t_NodeOffSet = 0 ; ULONG t_NodeIndex = 0 ; t_StatusCode = FindInBlock ( t_Node , a_BlockOffSet , a_Key , t_ChildOffSet , t_Element , t_NodeOffSet , t_NodeIndex ) ; if ( t_StatusCode == e_StatusCode_Success ) { if ( t_Element ) { t_StatusCode = e_StatusCode_AlreadyExists ; } else { t_StatusCode = a_Stack.Push ( a_BlockOffSet ) ; if ( t_StatusCode == e_StatusCode_Success ) { t_StatusCode = RecursiveInsert ( a_Stack , t_ChildOffSet , a_Key , a_Element ) ; } } m_BlockAllocator.ReleaseBlock ( t_Block ) ; } else { WmiAbsoluteBlockOffSet t_OffSet = a_BlockOffSet ; WmiBPKey t_Key = a_Key ; WmiBPElement t_Element = a_Element ; WmiBPKey t_ReBalanceKey ; WmiBPElement t_ReBalanceElement = a_Element ; WmiAbsoluteBlockOffSet t_LeftCutBlockOffSet = 0 ; WmiAbsoluteBlockOffSet t_RightCutBlockOffSet = 0 ; do { if ( t_ReBalanceElement ) { t_Node = ( WmiBPKeyNode * ) t_Block ; t_StatusCode = InsertInBlock ( t_Node , t_OffSet , t_Key , t_Element , t_ReBalanceKey , t_ReBalanceElement , t_LeftCutBlockOffSet , t_RightCutBlockOffSet ) ; m_BlockAllocator.ReleaseBlock ( t_Block ) ; if ( t_StatusCode == e_StatusCode_Success ) { WmiStatusCode t_TempStatusCode = a_Stack.Top ( t_OffSet ) ; if ( t_TempStatusCode != e_StatusCode_Success ) { if ( t_ReBalanceElement ) { t_OffSet = 0 ; t_Block = NULL ; t_StatusCode = m_BlockAllocator.AllocateBlock ( 1 , t_OffSet , t_Block ) ; if ( t_StatusCode == e_StatusCode_Success ) { WmiBPKeyNode *t_Node = ( WmiBPKeyNode * ) t_Block ; t_Node->SetFlags ( WMIBPLUS_TREE_FLAG_INTERNAL ) ; t_Node->SetNodeSize ( 1 ) ; t_Node->SetNodeOffSet ( t_OffSet ) ; t_Node->SetNodeStart ( 0 ) ; t_StatusCode = SetNode ( t_Node , sizeof ( WmiBPKeyNode ) , t_ReBalanceKey , t_ReBalanceElement , t_LeftCutBlockOffSet , t_RightCutBlockOffSet ) ; if ( t_StatusCode == e_StatusCode_Success ) { t_StatusCode = m_BlockAllocator.WriteBlock ( ( BYTE * ) & t_Node ) ; if ( t_StatusCode == e_StatusCode_Success ) { SetRoot ( t_OffSet ) ; #ifdef INSERT_DEBUG PrintNode ( L"\nRoot Creation" , t_Node , t_OffSet ) ; #endif } m_BlockAllocator.ReleaseBlock ( t_Block ) ; } else { m_BlockAllocator.ReleaseBlock ( t_Block ) ; m_BlockAllocator.FreeBlock ( 1 , t_OffSet ) ; } } } if ( t_ReBalanceKey.GetAllocated () ) { m_Allocator.Delete ( t_ReBalanceKey.GetData () ) ; } return t_StatusCode ; } else { m_BlockAllocator.ReleaseBlock ( t_Block ) ; if ( t_ReBalanceElement ) { t_Block = NULL ; t_StatusCode = m_BlockAllocator.ReadBlock ( 1 , t_OffSet , t_Block ) ; if ( t_Key.GetAllocated () ) { m_Allocator.Delete ( t_Key.GetData () ) ; } t_Key = t_ReBalanceKey ; t_Element = t_ReBalanceElement ; } a_Stack.Pop () ; } } } else { if ( t_Key.GetAllocated () ) { m_Allocator.Delete ( t_Key.GetData () ) ; } m_BlockAllocator.ReleaseBlock ( t_Block ) ; return e_StatusCode_Success ; } } while ( t_StatusCode == e_StatusCode_Success ) ; if ( t_Key.GetAllocated () ) { m_Allocator.Delete ( t_Key.GetData () ) ; } } } return t_StatusCode ; } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ WmiStatusCode WmiBPlusTree :: Insert ( const WmiBPKey &a_Key , const WmiBPElement &a_Element ) { #ifdef INSERT_DEBUG OutputDebugString ( L"\n/**************************************" ) ; wchar_t t_StringBuffer [ 1024 ] ; swprintf ( t_StringBuffer , L"\nKey = %I64x" , * ( UINT64 * ) a_Key.GetConstData () ) ; OutputDebugString ( t_StringBuffer ) ; OutputDebugString ( L"\n======================================" ) ; #endif WmiStatusCode t_StatusCode = e_StatusCode_Success ; if ( m_Root ) { WmiStack t_Stack ( m_Allocator ) ; t_StatusCode = t_Stack.Initialize () ; if ( t_StatusCode == e_StatusCode_Success ) { t_StatusCode = RecursiveInsert ( t_Stack , m_Root , a_Key , a_Element ) ; } } else { WmiAbsoluteBlockOffSet t_BlockOffSet = 0 ; BYTE *t_Block = NULL ; WmiStatusCode t_StatusCode = m_BlockAllocator.AllocateBlock ( 1 , t_BlockOffSet , t_Block ) ; if ( t_StatusCode == e_StatusCode_Success ) { WmiBPKeyNode *t_Node = ( WmiBPKeyNode * ) t_Block ; t_Node->SetFlags ( WMIBPLUS_TREE_FLAG_LEAF ) ; t_Node->SetNodeSize ( 1 ) ; t_Node->SetNodeOffSet ( t_BlockOffSet ) ; t_Node->SetNodeStart ( 0 ) ; t_StatusCode = SetLeafNode ( t_Node , sizeof ( WmiBPKeyNode ) , a_Key , a_Element ) ; if ( t_StatusCode == e_StatusCode_Success ) { t_StatusCode = m_BlockAllocator.WriteBlock ( ( BYTE * ) & t_Node ) ; if ( t_StatusCode == e_StatusCode_Success ) { SetRoot ( t_BlockOffSet ) ; } m_BlockAllocator.ReleaseBlock ( t_Block ) ; } else { m_BlockAllocator.ReleaseBlock ( t_Block ) ; m_BlockAllocator.FreeBlock ( 1 , t_BlockOffSet ) ; } } } if ( t_StatusCode == e_StatusCode_Success ) { m_Size ++ ; } #ifdef INSERT_DEBUG OutputDebugString ( L"\n**************************************\\" ) ; #endif return t_StatusCode ; } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ WmiStatusCode WmiBPlusTree :: StealSiblingNode ( WmiBPKeyNode *a_ParentNode , WmiAbsoluteBlockOffSet &a_ParentBlockOffSet , WmiBPKeyNode *a_Node , WmiAbsoluteBlockOffSet &a_BlockOffSet , WmiRelativeBlockOffSet &a_PositionBlockOffSet , WmiBPKeyNode *a_SiblingNode , WmiAbsoluteBlockOffSet &a_SiblingBlockOffSet , WmiAbsoluteBlockOffSet &a_LeftSiblingBlockOffSet , WmiAbsoluteBlockOffSet &a_RightSiblingBlockOffSet ) { WmiStatusCode t_StatusCode = e_StatusCode_Success ; ULONG t_InternalKeySize ; ULONG t_KeyOffSet ; ULONG t_ElementOffSet ; ULONG t_PointerOffSet ; #ifdef DELETE_DEBUG OutputDebugString ( L"\nSteal Sibling" ) ; PrintNode ( L"\nParent" , a_ParentNode , a_ParentBlockOffSet ) ; PrintNode ( L"\nNode" , a_Node , a_BlockOffSet ) ; PrintNode ( L"\nSibling" , a_SiblingNode , a_SiblingBlockOffSet ) ; #endif BOOL t_Leaf = ( ( a_Node->GetFlags () & WMIBPLUS_TREE_FLAG_LEAF ) == WMIBPLUS_TREE_FLAG_LEAF ) ; if ( t_Leaf ) { t_InternalKeySize = GetKeyTypeLength () + WmiBlockLeafKeyOffSet ; t_KeyOffSet = WmiBlockLeafKeyOffSet ; t_ElementOffSet = WmiBlockLeafKeyElementOffSet ; } else { t_InternalKeySize = GetKeyTypeLength () + WmiBlockKeyOffSet ; t_KeyOffSet = WmiBlockKeyOffSet ; t_ElementOffSet = WmiBlockKeyElementOffSet ; t_PointerOffSet = WmiBlockKeyPointerOffSet ; } WmiAbsoluteBlockOffSet t_StartBlockOffSet = sizeof ( WmiBPKeyNode ) ; if ( a_LeftSiblingBlockOffSet ) { /* * Shuffle node for insertion */ WmiRelativeBlockOffSet t_TotalSize = t_StartBlockOffSet + a_Node->GetNodeSize () * t_InternalKeySize ; MoveMemory ( ( ( BYTE * ) a_Node ) + t_StartBlockOffSet + t_InternalKeySize , ( ( BYTE * ) a_Node ) + t_StartBlockOffSet , ( ULONG ) t_TotalSize + t_InternalKeySize ) ; /* * Copy parent key down */ BYTE *t_FromBuffer = ( ( BYTE * ) a_ParentNode ) + a_PositionBlockOffSet + WmiBlockKeyOffSet ; BYTE *t_ToBuffer = ( ( BYTE * ) a_Node ) + t_StartBlockOffSet + t_KeyOffSet ; CopyMemory ( t_ToBuffer , t_FromBuffer , GetKeyTypeLength () , ) ; t_FromBuffer = ( ( BYTE * ) a_ParentNode ) + a_PositionBlockOffSet + WmiBlockKeyElementOffSet ; t_ToBuffer = ( ( BYTE * ) a_Node ) + t_StartBlockOffSet + t_ElementOffSet ; CopyMemory ( t_ToBuffer , t_FromBuffer , sizeof ( WmiBPElement ) ) ; /* * Copy from left */ t_FromBuffer = ( ( BYTE * ) a_SiblingNode ) + t_StartBlockOffSet + ( a_SiblingNode->GetNodeSize () - 1 ) * t_InternalKeySize + t_KeyOffSet ; t_ToBuffer = ( ( BYTE * ) a_ParentNode ) + a_PositionBlockOffSet + WmiBlockKeyOffSet ; CopyMemory ( t_ToBuffer , t_FromBuffer , GetKeyTypeLength () , ) ; t_FromBuffer = ( ( BYTE * ) a_SiblingNode ) + t_StartBlockOffSet + ( a_SiblingNode->GetNodeSize () - 1 ) * t_InternalKeySize + t_ElementOffSet ; t_ToBuffer = ( ( BYTE * ) a_ParentNode ) + a_PositionBlockOffSet + WmiBlockKeyElementOffSet ; CopyMemory ( t_ToBuffer , t_FromBuffer , sizeof ( WmiBPElement ) ) ; /* * Copy pointers from sibling to node */ if ( t_Leaf == FALSE ) { t_FromBuffer = ( ( BYTE * ) a_SiblingNode ) + t_StartBlockOffSet + a_SiblingNode->GetNodeSize () * t_InternalKeySize + t_PointerOffSet ; t_ToBuffer = ( ( BYTE * ) a_Node ) + t_StartBlockOffSet + t_PointerOffSet ; CopyMemory ( t_ToBuffer , t_FromBuffer , sizeof ( WmiAbsoluteBlockOffSet ) ) ; } } else { /* * Copy parent key down */ BYTE *t_FromBuffer = ( ( BYTE * ) a_ParentNode ) + a_PositionBlockOffSet + WmiBlockKeyOffSet ; BYTE *t_ToBuffer = ( ( BYTE * ) a_Node ) + t_StartBlockOffSet + a_Node->GetNodeSize () * t_InternalKeySize + t_KeyOffSet ; CopyMemory ( t_ToBuffer , t_FromBuffer , GetKeyTypeLength () , ) ; t_FromBuffer = ( ( BYTE * ) a_ParentNode ) + a_PositionBlockOffSet + WmiBlockKeyElementOffSet ; t_ToBuffer = ( ( BYTE * ) a_Node ) + t_StartBlockOffSet + a_Node->GetNodeSize () * t_InternalKeySize + t_ElementOffSet ; CopyMemory ( t_ToBuffer , t_FromBuffer , sizeof ( WmiBPElement ) ) ; /* * Copy from right */ t_FromBuffer = ( ( BYTE * ) a_SiblingNode ) + t_StartBlockOffSet + t_KeyOffSet ; t_ToBuffer = ( ( BYTE * ) a_ParentNode ) + a_PositionBlockOffSet + WmiBlockKeyOffSet ; CopyMemory ( t_ToBuffer , t_FromBuffer , GetKeyTypeLength () , ) ; t_FromBuffer = ( ( BYTE * ) a_SiblingNode ) + t_StartBlockOffSet + t_ElementOffSet ; t_ToBuffer = ( ( BYTE * ) a_ParentNode ) + a_PositionBlockOffSet + WmiBlockKeyElementOffSet ; CopyMemory ( t_ToBuffer , t_FromBuffer , sizeof ( WmiBPElement ) ) ; if ( t_Leaf == FALSE ) { t_FromBuffer = ( ( BYTE * ) a_SiblingNode ) + t_StartBlockOffSet + t_PointerOffSet ; t_ToBuffer = ( ( BYTE * ) a_Node ) + t_StartBlockOffSet + a_Node->GetNodeSize () * t_InternalKeySize + t_InternalKeySize + WmiBlockKeyPointerOffSet ; CopyMemory ( t_ToBuffer , t_FromBuffer , sizeof ( WmiAbsoluteBlockOffSet ) ) ; } /* * Shuffle memory due to deletion */ WmiRelativeBlockOffSet t_TotalSize = a_SiblingNode->GetNodeSize () * t_InternalKeySize - t_InternalKeySize ; MoveMemory ( ( ( BYTE * ) a_SiblingNode ) + t_StartBlockOffSet , ( ( BYTE * ) a_SiblingNode ) + t_StartBlockOffSet + t_InternalKeySize , ( ULONG ) t_TotalSize + ( t_Leaf ? 0 : t_InternalKeySize ) ) ; } a_Node->SetNodeSize ( a_Node->GetNodeSize () + 1 ) ; a_SiblingNode->SetNodeSize ( a_SiblingNode->GetNodeSize () - 1 ) ; #ifdef DELETE_DEBUG PrintNode ( L"\nParent" , a_ParentNode , a_ParentBlockOffSet ) ; PrintNode ( L"\nSibling" , a_SiblingNode , a_SiblingBlockOffSet ) ; PrintNode ( L"\nNode" , a_Node , a_BlockOffSet ) ; #endif t_StatusCode = m_BlockAllocator.WriteBlock ( ( BYTE * ) & a_Node ) ; if ( t_StatusCode == e_StatusCode_Success ) { t_StatusCode = m_BlockAllocator.WriteBlock ( ( BYTE * ) & a_SiblingNode ) ; if ( t_StatusCode == e_StatusCode_Success ) { t_StatusCode = m_BlockAllocator.WriteBlock ( ( BYTE * ) & a_ParentNode ) ; } } return t_StatusCode ; } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ WmiStatusCode WmiBPlusTree :: MergeSiblingNode ( WmiBPKeyNode *a_ParentNode , WmiAbsoluteBlockOffSet &a_ParentBlockOffSet , WmiBPKeyNode *a_Node , WmiAbsoluteBlockOffSet &a_BlockOffSet , WmiRelativeBlockOffSet &a_PositionBlockOffSet , WmiBPKeyNode *a_SiblingNode , WmiAbsoluteBlockOffSet &a_SiblingBlockOffSet , WmiAbsoluteBlockOffSet &a_LeftSiblingBlockOffSet , WmiAbsoluteBlockOffSet &a_RightSiblingBlockOffSet ) { WmiStatusCode t_StatusCode = e_StatusCode_Success ; #ifdef DELETE_DEBUG OutputDebugString ( L"\nMerging Node and Sibling" ) ; PrintNode ( L"\nParent" , a_ParentNode , a_ParentBlockOffSet ) ; PrintNode ( L"\nNode" , a_Node , a_BlockOffSet ) ; PrintNode ( L"\nSibling" , a_SiblingNode , a_SiblingBlockOffSet ) ; #endif ULONG t_InternalKeySize ; ULONG t_KeyOffSet ; ULONG t_ElementOffSet ; ULONG t_PointerOffSet ; BOOL t_Leaf = ( ( a_Node->GetFlags () & WMIBPLUS_TREE_FLAG_LEAF ) == WMIBPLUS_TREE_FLAG_LEAF ) ; if ( t_Leaf ) { t_InternalKeySize = GetKeyTypeLength () + WmiBlockLeafKeyOffSet ; t_KeyOffSet = WmiBlockLeafKeyOffSet ; t_ElementOffSet = WmiBlockLeafKeyElementOffSet ; } else { t_InternalKeySize = GetKeyTypeLength () + WmiBlockKeyOffSet ; t_KeyOffSet = WmiBlockKeyOffSet ; t_ElementOffSet = WmiBlockKeyElementOffSet ; t_PointerOffSet = WmiBlockKeyPointerOffSet ; } WmiAbsoluteBlockOffSet t_StartBlockOffSet = sizeof ( WmiBPKeyNode ) ; /* * Copy sibling key up to parent */ if ( a_LeftSiblingBlockOffSet ) { /* * Copy parent key down */ BYTE *t_FromBuffer = ( ( BYTE * ) a_ParentNode ) + a_PositionBlockOffSet + WmiBlockKeyOffSet ; BYTE *t_ToBuffer = ( ( BYTE * ) a_SiblingNode ) + t_StartBlockOffSet + a_SiblingNode->GetNodeSize () * t_InternalKeySize + t_KeyOffSet ; CopyMemory ( t_ToBuffer , t_FromBuffer , GetKeyTypeLength () , ) ; t_FromBuffer = ( ( BYTE * ) a_ParentNode ) + a_PositionBlockOffSet + WmiBlockKeyElementOffSet ; t_ToBuffer = ( ( BYTE * ) a_SiblingNode ) + t_StartBlockOffSet + a_SiblingNode->GetNodeSize () * t_InternalKeySize + t_ElementOffSet ; CopyMemory ( t_ToBuffer , t_FromBuffer , sizeof ( WmiBPElement ) ) ; /* * Copy node into sibling */ if ( t_Leaf ) { WmiRelativeBlockOffSet t_TotalSize = a_Node->GetNodeSize () * t_InternalKeySize ; CopyMemory ( ( ( BYTE * ) a_SiblingNode ) + t_StartBlockOffSet + a_SiblingNode->GetNodeSize () * t_InternalKeySize + t_InternalKeySize , ( ( BYTE * ) a_Node ) + t_StartBlockOffSet , ( ULONG ) t_TotalSize ) ; } else { WmiRelativeBlockOffSet t_TotalSize = a_Node->GetNodeSize () * t_InternalKeySize ; CopyMemory ( ( ( BYTE * ) a_SiblingNode ) + t_StartBlockOffSet + a_SiblingNode->GetNodeSize () * t_InternalKeySize + t_InternalKeySize , ( ( BYTE * ) a_Node ) + t_StartBlockOffSet , ( ULONG ) t_TotalSize + t_InternalKeySize ) ; } /* * Shuffle memory due to deletion */ ULONG t_ParentInternalKeySize = WmiBlockKeyOffSet + GetKeyTypeLength () ; WmiRelativeBlockOffSet t_TotalSize = t_StartBlockOffSet + ( a_ParentNode->GetNodeSize () * t_ParentInternalKeySize ) ; WmiRelativeBlockOffSet t_MoveSize = t_TotalSize - a_PositionBlockOffSet ; MoveMemory ( ( ( BYTE * ) a_ParentNode ) + a_PositionBlockOffSet , ( ( BYTE * ) a_ParentNode ) + a_PositionBlockOffSet + t_ParentInternalKeySize , ( ULONG ) t_MoveSize ) ; CopyMemory ( ( ( BYTE * ) a_ParentNode ) + a_PositionBlockOffSet + WmiBlockKeyPointerOffSet , ( BYTE * ) & a_SiblingBlockOffSet , sizeof ( WmiAbsoluteBlockOffSet ) ) ; a_ParentNode->SetNodeSize ( a_ParentNode->GetNodeSize () - 1 ) ; a_SiblingNode->SetNodeSize ( a_SiblingNode->GetNodeSize () + a_Node->GetNodeSize () + 1 ) ; #ifdef DELETE_DEBUG PrintNode ( L"\nParent" , a_ParentNode , a_ParentBlockOffSet ) ; PrintNode ( L"\nSibling" , a_SiblingNode , a_SiblingBlockOffSet ) ; #endif t_StatusCode = m_BlockAllocator.FreeBlock ( 1 , a_BlockOffSet ) ; if ( t_StatusCode == e_StatusCode_Success ) { t_StatusCode = m_BlockAllocator.WriteBlock ( ( BYTE * ) & a_SiblingNode ) ; if ( t_StatusCode == e_StatusCode_Success ) { t_StatusCode = m_BlockAllocator.WriteBlock ( ( BYTE * ) & a_ParentNode ) ; } } } else { /* * Copy parent key down */ BYTE *t_FromBuffer = ( ( BYTE * ) a_ParentNode ) + a_PositionBlockOffSet + WmiBlockKeyOffSet ; BYTE *t_ToBuffer = ( ( BYTE * ) a_Node ) + t_StartBlockOffSet + a_Node->GetNodeSize () * t_InternalKeySize + t_KeyOffSet ; CopyMemory ( t_ToBuffer , t_FromBuffer , GetKeyTypeLength () , ) ; t_FromBuffer = ( ( BYTE * ) a_ParentNode ) + a_PositionBlockOffSet + WmiBlockKeyElementOffSet ; t_ToBuffer = ( ( BYTE * ) a_Node ) + t_StartBlockOffSet + a_Node->GetNodeSize () * t_InternalKeySize + t_ElementOffSet ; CopyMemory ( t_ToBuffer , t_FromBuffer , sizeof ( WmiBPElement ) ) ; /* * Copy sibling into node */ if ( t_Leaf ) { WmiRelativeBlockOffSet t_TotalSize = a_SiblingNode->GetNodeSize () * t_InternalKeySize ; CopyMemory ( ( ( BYTE * ) a_Node ) + t_StartBlockOffSet + a_Node->GetNodeSize () * t_InternalKeySize + t_InternalKeySize , ( ( BYTE * ) a_SiblingNode ) + t_StartBlockOffSet , ( ULONG ) t_TotalSize ) ; } else { WmiRelativeBlockOffSet t_TotalSize = a_SiblingNode->GetNodeSize () * t_InternalKeySize ; CopyMemory ( ( ( BYTE * ) a_Node ) + t_StartBlockOffSet + a_Node->GetNodeSize () * t_InternalKeySize + t_InternalKeySize , ( ( BYTE * ) a_SiblingNode ) + t_StartBlockOffSet , ( ULONG ) t_TotalSize + t_InternalKeySize ) ; } /* * Shuffle memory due to deletion */ ULONG t_ParentInternalKeySize = WmiBlockKeyOffSet + GetKeyTypeLength () ; WmiRelativeBlockOffSet t_TotalSize = t_StartBlockOffSet + a_ParentNode->GetNodeSize () * t_ParentInternalKeySize ; WmiRelativeBlockOffSet t_MoveSize = t_TotalSize - a_PositionBlockOffSet ; MoveMemory ( ( ( BYTE * ) a_ParentNode ) + a_PositionBlockOffSet , ( ( BYTE * ) a_ParentNode ) + a_PositionBlockOffSet + t_ParentInternalKeySize , ( ULONG ) t_MoveSize ) ; CopyMemory ( ( ( BYTE * ) a_ParentNode ) + a_PositionBlockOffSet + WmiBlockKeyPointerOffSet , ( BYTE * ) & a_BlockOffSet , sizeof ( WmiAbsoluteBlockOffSet ) ) ; a_ParentNode->SetNodeSize ( a_ParentNode->GetNodeSize () - 1 ) ; a_Node->SetNodeSize ( a_Node->GetNodeSize () + a_SiblingNode->GetNodeSize () + 1 ) ; #ifdef DELETE_DEBUG PrintNode ( L"\nParent" , a_ParentNode , a_ParentBlockOffSet ) ; PrintNode ( L"\nNode" , a_Node , a_BlockOffSet ) ; #endif t_StatusCode = m_BlockAllocator.FreeBlock ( 1 , a_SiblingBlockOffSet ) ; if ( t_StatusCode == e_StatusCode_Success ) { t_StatusCode = m_BlockAllocator.WriteBlock ( ( BYTE * ) & a_Node ) ; if ( t_StatusCode == e_StatusCode_Success ) { t_StatusCode = m_BlockAllocator.WriteBlock ( ( BYTE * ) & a_ParentNode ) ; } } } return t_StatusCode ; } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ WmiStatusCode WmiBPlusTree :: LocateSuitableSibling ( WmiBPKeyNode *a_ParentNode , WmiAbsoluteBlockOffSet &a_ParentBlockOffSet , WmiBPKeyNode *a_Node , WmiAbsoluteBlockOffSet &a_BlockOffSet , WmiRelativeBlockOffSet &a_PositionBlockOffSet , WmiAbsoluteBlockOffSet &a_LeftSiblingBlockOffSet , WmiAbsoluteBlockOffSet &a_RightSiblingBlockOffSet ) { WmiStatusCode t_StatusCode = e_StatusCode_Success ; WmiAbsoluteBlockOffSet t_BlockOffSet = sizeof ( WmiBPKeyNode ) ; ULONG t_InternalKeySize = GetKeyTypeLength () + WmiBlockKeyOffSet ; ULONG t_NodeStart = a_ParentNode->GetNodeStart () ; ULONG t_NodeSize = a_ParentNode->GetNodeSize () ; for ( ULONG t_Index = t_NodeStart ; t_Index <= t_NodeSize ; t_Index ++ ) { WmiAbsoluteBlockOffSet t_PointerBlockOffSet ; CopyMemory ( ( BYTE * ) & t_PointerBlockOffSet , ( ( BYTE * ) ( a_ParentNode ) ) + t_BlockOffSet + WmiBlockKeyPointerOffSet , sizeof ( WmiAbsoluteBlockOffSet ) ) ; if ( t_PointerBlockOffSet == a_BlockOffSet ) { if ( t_Index ) { a_PositionBlockOffSet = t_BlockOffSet - t_InternalKeySize ; CopyMemory ( ( BYTE * ) & a_LeftSiblingBlockOffSet , ( ( BYTE * ) ( a_ParentNode ) ) + t_BlockOffSet - t_InternalKeySize + WmiBlockKeyPointerOffSet , sizeof ( WmiAbsoluteBlockOffSet ) ) ; a_RightSiblingBlockOffSet = 0 ; } else { a_PositionBlockOffSet = t_BlockOffSet ; a_LeftSiblingBlockOffSet = 0 ; CopyMemory ( ( BYTE * ) & a_RightSiblingBlockOffSet , ( ( BYTE * ) ( a_ParentNode ) ) + t_BlockOffSet + t_InternalKeySize + WmiBlockKeyPointerOffSet , sizeof ( WmiAbsoluteBlockOffSet ) ) ; } return t_StatusCode ; } t_BlockOffSet = t_BlockOffSet + t_InternalKeySize ; } t_StatusCode = e_StatusCode_NotFound ; return t_StatusCode ; } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ WmiStatusCode WmiBPlusTree :: DeleteReBalance ( WmiBPKeyNode *a_ParentNode , WmiAbsoluteBlockOffSet &a_ParentBlockOffSet , WmiBPKeyNode *a_Node , WmiAbsoluteBlockOffSet &a_BlockOffSet ) { WmiStatusCode t_StatusCode = e_StatusCode_Success ; WmiAbsoluteBlockOffSet t_StartBlockOffSet = sizeof ( WmiBPKeyNode ) ; ULONG t_InternalKeySize = GetKeyTypeLength () + WmiBlockKeyOffSet ; WmiRelativeBlockOffSet t_PositionBlockOffSet ; WmiAbsoluteBlockOffSet t_LeftSiblingBlockOffSet ; WmiAbsoluteBlockOffSet t_RightSiblingBlockOffSet ; t_StatusCode = LocateSuitableSibling ( a_ParentNode , a_ParentBlockOffSet , a_Node , a_BlockOffSet , t_PositionBlockOffSet , t_LeftSiblingBlockOffSet , t_RightSiblingBlockOffSet ) ; if ( t_StatusCode == e_StatusCode_Success ) { BYTE *t_Block = NULL ; if ( t_LeftSiblingBlockOffSet ) { t_StatusCode = m_BlockAllocator.ReadBlock ( 1 , t_LeftSiblingBlockOffSet , t_Block ) ; } else { t_StatusCode = m_BlockAllocator.ReadBlock ( 1 , t_RightSiblingBlockOffSet , t_Block ) ; } if ( t_StatusCode == e_StatusCode_Success ) { WmiBPKeyNode *t_SiblingNode = ( WmiBPKeyNode * ) t_Block ; BOOL t_Leaf = ( ( a_Node->GetFlags () & WMIBPLUS_TREE_FLAG_LEAF ) == WMIBPLUS_TREE_FLAG_LEAF ) ; ULONG t_Balance = t_Leaf ? MaxLeafKeys () : MaxKeys () ; if ( t_SiblingNode->GetNodeSize () > ( t_Balance >> 1 ) ) { /* * Steal a key */ t_StatusCode = StealSiblingNode ( a_ParentNode , a_ParentBlockOffSet , a_Node , a_BlockOffSet , t_PositionBlockOffSet , t_SiblingNode , t_LeftSiblingBlockOffSet ? t_LeftSiblingBlockOffSet : t_RightSiblingBlockOffSet , t_LeftSiblingBlockOffSet , t_RightSiblingBlockOffSet ) ; } else { /* * Merge sibling nodes */ t_StatusCode = MergeSiblingNode ( a_ParentNode , a_ParentBlockOffSet , a_Node , a_BlockOffSet , t_PositionBlockOffSet , t_SiblingNode , t_LeftSiblingBlockOffSet ? t_LeftSiblingBlockOffSet : t_RightSiblingBlockOffSet , t_LeftSiblingBlockOffSet , t_RightSiblingBlockOffSet ) ; } m_BlockAllocator.ReleaseBlock ( t_Block ) ; } } return t_StatusCode ; } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ WmiStatusCode WmiBPlusTree :: RecursiveDeleteFixup ( WmiStack &a_Stack , WmiBPKeyNode *a_RootNode , WmiAbsoluteBlockOffSet &a_RootBlockOffSet , WmiBPKeyNode *a_Node , WmiAbsoluteBlockOffSet &a_BlockOffSet , WmiRelativeBlockOffSet &a_PositionBlockOffSet ) { WmiStatusCode t_StatusCode = e_StatusCode_Success ; WmiAbsoluteBlockOffSet t_StartBlockOffSet = sizeof ( WmiBPKeyNode ) ; ULONG t_InternalKeySize = GetKeyTypeLength () ; ULONG t_KeyOffSet ; BOOL t_Leaf = ( ( a_Node->GetFlags () & WMIBPLUS_TREE_FLAG_LEAF ) == WMIBPLUS_TREE_FLAG_LEAF ) ; if ( t_Leaf ) { t_KeyOffSet = WmiBlockLeafKeyOffSet ; t_InternalKeySize = t_InternalKeySize + WmiBlockLeafKeyOffSet ; } else { t_KeyOffSet = WmiBlockKeyOffSet ; t_InternalKeySize = t_InternalKeySize + WmiBlockKeyOffSet ; } ULONG t_NodeSize = a_Node->GetNodeSize () ; if ( t_Leaf ) { if ( a_RootBlockOffSet == a_BlockOffSet ) { /* * Shuffle memory to remove deleted fixup node */ WmiRelativeBlockOffSet t_TotalSize = t_StartBlockOffSet + a_Node->GetNodeSize () * t_InternalKeySize ; WmiRelativeBlockOffSet t_MoveSize = t_TotalSize - a_PositionBlockOffSet - t_InternalKeySize ; MoveMemory ( ( ( BYTE * ) a_Node ) + a_PositionBlockOffSet , ( ( BYTE * ) a_Node ) + a_PositionBlockOffSet + t_InternalKeySize , ( ULONG ) t_MoveSize + ( t_Leaf ? 0 : t_InternalKeySize ) ) ; } else { /* * Copy node up to place we deleted from. */ #ifdef DELETE_DEBUG PrintNode ( L"\nCopy Down a_RootNode" , a_RootNode , a_RootBlockOffSet ) ; PrintNode ( L"\na_Node" , a_Node , a_BlockOffSet ) ; #endif BYTE *t_FromBuffer = ( ( BYTE * ) a_Node ) + t_StartBlockOffSet + WmiBlockLeafKeyOffSet ; BYTE *t_ToBuffer = ( ( BYTE * ) a_RootNode ) + a_PositionBlockOffSet + WmiBlockKeyOffSet ; CopyMemory ( t_ToBuffer , t_FromBuffer , GetKeyTypeLength () , ) ; t_FromBuffer = ( ( BYTE * ) a_Node ) + t_StartBlockOffSet + WmiBlockLeafKeyElementOffSet ; t_ToBuffer = ( ( BYTE * ) a_RootNode ) + a_PositionBlockOffSet + WmiBlockKeyElementOffSet ; CopyMemory ( t_ToBuffer , t_FromBuffer , sizeof ( WmiBPElement ) ) ; /* * Shuffle memory to remove deleted fixup node */ WmiRelativeBlockOffSet t_TotalSize = a_Node->GetNodeSize () * t_InternalKeySize - t_InternalKeySize ; MoveMemory ( ( ( BYTE * ) a_Node ) + t_StartBlockOffSet , ( ( BYTE * ) a_Node ) + t_StartBlockOffSet + t_InternalKeySize , ( ULONG ) t_TotalSize + ( t_Leaf ? 0 : t_InternalKeySize ) ) ; } a_Node->SetNodeSize ( a_Node->GetNodeSize () - 1 ) ; #ifdef DELETE_DEBUG PrintNode ( L"\na_Node" , a_Node , a_BlockOffSet ) ; #endif t_StatusCode = m_BlockAllocator.WriteBlock ( ( BYTE * ) & a_Node ) ; if ( t_StatusCode == e_StatusCode_Success ) { /* * Finally re balance as required */ WmiBPKeyNode *t_Node = a_Node ; WmiAbsoluteBlockOffSet t_BlockOffSet = a_BlockOffSet ; m_BlockAllocator.AddRefBlock ( ( BYTE * ) & a_Node ) ; do { BOOL t_ReBalance ; if ( t_Leaf ) { t_ReBalance = t_Node->GetNodeSize () < ( MaxLeafKeys () >> 1 ) ? TRUE : FALSE ; } else { t_ReBalance = t_Node->GetNodeSize () < ( MaxKeys () >> 1 ) ? TRUE : FALSE ; } if ( t_ReBalance ) { WmiAbsoluteBlockOffSet t_ParentOffSet = 0 ; WmiStatusCode t_TempStatusCode = a_Stack.Top ( t_ParentOffSet ) ; if ( t_TempStatusCode == e_StatusCode_Success ) { m_BlockAllocator.ReleaseBlock ( ( BYTE * ) & t_Node ) ; BYTE *t_Block = NULL ; t_StatusCode = m_BlockAllocator.ReadBlock ( 1 , t_ParentOffSet , t_Block ) ; if ( t_StatusCode == e_StatusCode_Success ) { WmiBPKeyNode *t_ParentNode = ( WmiBPKeyNode * ) t_Block ; t_StatusCode = DeleteReBalance ( t_ParentNode , t_ParentOffSet , t_Node , t_BlockOffSet ) ; t_Node = t_ParentNode ; t_BlockOffSet = t_ParentOffSet ; t_Leaf = ( ( t_Node->GetFlags () & WMIBPLUS_TREE_FLAG_LEAF ) == WMIBPLUS_TREE_FLAG_LEAF ) ; } a_Stack.Pop () ; } else { if ( t_Leaf ) { if ( t_Node->GetNodeSize () == 0 ) { if ( t_BlockOffSet == GetRoot () ) { SetRoot ( 0 ) ; } m_BlockAllocator.ReleaseBlock ( ( BYTE * ) & t_Node ) ; m_BlockAllocator.FreeBlock ( 1 , t_BlockOffSet ) ; } else { m_BlockAllocator.ReleaseBlock ( ( BYTE * ) & t_Node ) ; } } else { if ( t_Node->GetNodeSize () == 0 ) { WmiAbsoluteBlockOffSet t_ChildOffSet = 0 ; CopyMemory ( ( BYTE * ) & t_ChildOffSet , ( ( BYTE * ) ( t_Node ) ) + t_StartBlockOffSet + WmiBlockKeyPointerOffSet , sizeof ( WmiAbsoluteBlockOffSet ) ) ; SetRoot ( t_ChildOffSet ) ; m_BlockAllocator.ReleaseBlock ( ( BYTE * ) & t_Node ) ; m_BlockAllocator.FreeBlock ( 1 , t_BlockOffSet ) ; } else { m_BlockAllocator.ReleaseBlock ( ( BYTE * ) & t_Node ) ; } } return t_StatusCode ; } } else { m_BlockAllocator.ReleaseBlock ( ( BYTE * ) & t_Node ) ; return t_StatusCode ; } } while ( t_StatusCode == e_StatusCode_Success ) ; } } else { WmiAbsoluteBlockOffSet t_ChildOffSet = 0 ; CopyMemory ( ( BYTE * ) & t_ChildOffSet , ( ( BYTE * ) ( a_Node ) ) + t_StartBlockOffSet + WmiBlockKeyPointerOffSet , sizeof ( WmiAbsoluteBlockOffSet ) ) ; BYTE *t_Block = NULL ; t_StatusCode = m_BlockAllocator.ReadBlock ( 1 , t_ChildOffSet , t_Block ) ; if ( t_StatusCode == e_StatusCode_Success ) { WmiBPKeyNode *t_Node = ( WmiBPKeyNode * ) t_Block ; t_StatusCode = a_Stack.Push ( a_BlockOffSet ) ; if ( t_StatusCode == e_StatusCode_Success ) { RecursiveDeleteFixup ( a_Stack , a_RootNode , a_RootBlockOffSet , t_Node , t_ChildOffSet , a_PositionBlockOffSet ) ; } m_BlockAllocator.ReleaseBlock ( t_Block ) ; } } return t_StatusCode ; } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ WmiStatusCode WmiBPlusTree :: DeleteFixup ( WmiStack &a_Stack , WmiBPKeyNode *a_Node , WmiAbsoluteBlockOffSet &a_BlockOffSet , WmiRelativeBlockOffSet &a_PositionBlockOffSet ) { WmiStatusCode t_StatusCode = e_StatusCode_Success ; WmiAbsoluteBlockOffSet t_BlockOffSet = sizeof ( WmiBPKeyNode ) ; ULONG t_InternalKeySize = GetKeyTypeLength () ; ULONG t_KeyOffSet ; BOOL t_Leaf = ( ( a_Node->GetFlags () & WMIBPLUS_TREE_FLAG_LEAF ) == WMIBPLUS_TREE_FLAG_LEAF ) ; if ( t_Leaf ) { t_KeyOffSet = WmiBlockLeafKeyOffSet ; t_InternalKeySize = t_InternalKeySize + WmiBlockLeafKeyOffSet ; } else { t_KeyOffSet = WmiBlockKeyOffSet ; t_InternalKeySize = t_InternalKeySize + WmiBlockKeyOffSet ; } ULONG t_NodeSize = a_Node->GetNodeSize () ; if ( t_Leaf ) { t_StatusCode = RecursiveDeleteFixup ( a_Stack , a_Node , a_BlockOffSet , a_Node , a_BlockOffSet , a_PositionBlockOffSet ) ; } else { /* * Move right one and descend left most to get next key. */ WmiAbsoluteBlockOffSet t_ChildOffSet = 0 ; CopyMemory ( ( BYTE * ) & t_ChildOffSet , ( ( BYTE * ) ( a_Node ) ) + a_PositionBlockOffSet + t_InternalKeySize + WmiBlockKeyPointerOffSet , sizeof ( WmiAbsoluteBlockOffSet ) ) ; BYTE *t_Block = NULL ; t_StatusCode = m_BlockAllocator.ReadBlock ( 1 , t_ChildOffSet , t_Block ) ; if ( t_StatusCode == e_StatusCode_Success ) { WmiBPKeyNode *t_ChildNode = ( WmiBPKeyNode * ) t_Block ; t_StatusCode = RecursiveDeleteFixup ( a_Stack , a_Node , a_BlockOffSet , t_ChildNode , t_ChildOffSet , a_PositionBlockOffSet ) ; m_BlockAllocator.ReleaseBlock ( t_Block ) ; } } return t_StatusCode ; } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ WmiStatusCode WmiBPlusTree :: RecursiveDelete ( WmiStack &a_Stack , WmiAbsoluteBlockOffSet &a_BlockOffSet , const WmiBPKey &a_Key , WmiBPElement &a_Element ) { WmiAbsoluteBlockOffSet t_ChildOffSet = 0 ; WmiBPElement t_Element = 0 ; BYTE *t_Block = NULL ; WmiStatusCode t_StatusCode = m_BlockAllocator.ReadBlock ( 1 , a_BlockOffSet , t_Block ) ; if ( t_StatusCode == e_StatusCode_Success ) { WmiBPKeyNode *t_Node = ( WmiBPKeyNode * ) t_Block ; WmiRelativeBlockOffSet t_NodeOffSet = 0 ; ULONG t_NodeIndex = 0 ; t_StatusCode = FindInBlock ( t_Node , a_BlockOffSet , a_Key , t_ChildOffSet , t_Element , t_NodeOffSet , t_NodeIndex ) ; if ( t_StatusCode == e_StatusCode_Success ) { if ( t_Element ) { BOOL t_Leaf = ( ( t_Node->GetFlags () & WMIBPLUS_TREE_FLAG_LEAF ) == WMIBPLUS_TREE_FLAG_LEAF ) ; if ( t_Leaf == FALSE ) { t_StatusCode = a_Stack.Push ( a_BlockOffSet ) ; } if ( t_StatusCode == e_StatusCode_Success ) { t_StatusCode = DeleteFixup ( a_Stack , t_Node , a_BlockOffSet , t_NodeOffSet ) ; } } else { t_StatusCode = a_Stack.Push ( a_BlockOffSet ) ; if ( t_StatusCode == e_StatusCode_Success ) { t_StatusCode = RecursiveDelete ( a_Stack , t_ChildOffSet , a_Key , a_Element ) ; } } } else { t_StatusCode = e_StatusCode_NotFound ; } m_BlockAllocator.ReleaseBlock ( t_Block ) ; } return t_StatusCode ; } /****************************************************************************** * * Name: * * * Description: * * *****************************************************************************/ WmiStatusCode WmiBPlusTree :: Delete ( const WmiBPKey &a_Key , WmiBPElement &a_Element ) { #ifdef DELETE_DEBUG OutputDebugString ( L"\n/**************************************" ) ; wchar_t t_StringBuffer [ 1024 ] ; swprintf ( t_StringBuffer , L"\nKey = %I64x" , * ( UINT64 * ) a_Key.GetConstData () ) ; OutputDebugString ( t_StringBuffer ) ; OutputDebugString ( L"\n======================================" ) ; #endif WmiStatusCode t_StatusCode = e_StatusCode_Success ; if ( m_Root ) { WmiStack t_Stack ( m_Allocator ) ; t_StatusCode = t_Stack.Initialize () ; if ( t_StatusCode == e_StatusCode_Success ) { t_StatusCode = RecursiveDelete ( t_Stack , m_Root , a_Key , a_Element ) ; } } else { t_StatusCode = e_StatusCode_NotFound ; } if ( t_StatusCode == e_StatusCode_Success ) { m_Size -- ; } #ifdef DELETE_DEBUG OutputDebugString ( L"\n**************************************\\" ) ; #endif return t_StatusCode ; } #endif _BPLUSTREE_CPP