PageRenderTime 41ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/Alpha/Source/Libraries/GSF.SortedTreeStore/SortedTreeStore/Tree/SortedTreeNodeBase_Remove'2.cs

#
C# | 237 lines | 171 code | 30 blank | 36 comment | 50 complexity | e73263f4155258a4a2c24abb0dd2e228 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, EPL-1.0
  1. //******************************************************************************************************
  2. // SortedTreeNodeBase_Remove`2.cs - Gbtc
  3. //
  4. // Copyright © 2013, Grid Protection Alliance. All Rights Reserved.
  5. //
  6. // Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
  7. // the NOTICE file distributed with this work for additional information regarding copyright ownership.
  8. // The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
  9. // not use this file except in compliance with the License. You may obtain a copy of the License at:
  10. //
  11. // http://www.opensource.org/licenses/eclipse-1.0.php
  12. //
  13. // Unless agreed to in writing, the subject software distributed under the License is distributed on an
  14. // "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
  15. // License for the specific language governing permissions and limitations.
  16. //
  17. // Code Modification History:
  18. // ----------------------------------------------------------------------------------------------------
  19. // 4/16/2013 - Steven E. Chisholm
  20. // Generated original version of source code.
  21. //
  22. //******************************************************************************************************
  23. using System;
  24. using GSF.SortedTreeStore.Types;
  25. namespace GSF.SortedTreeStore.Tree
  26. {
  27. public unsafe partial class SortedTreeNodeBase<TKey, TValue>
  28. {
  29. //ToDO: Checked
  30. /// <summary>
  31. /// Tries to remove the key from the Node.
  32. /// </summary>
  33. /// <param name="key"></param>
  34. /// <returns></returns>
  35. public bool TryRemove(TKey key)
  36. {
  37. if (ValidBytes > m_minRecordNodeBytes &&
  38. KeyMethods.IsLessThanOrEqualTo(LowerKey, key) &&
  39. KeyMethods.IsLessThan(key, UpperKey))
  40. {
  41. int index = GetIndexOf(key);
  42. if (index < 0)
  43. return false;
  44. if (RemoveUnlessOverflow(index))
  45. return true;
  46. }
  47. return TryRemove2(key);
  48. }
  49. //ToDO: Checked
  50. protected bool TryRemove2(TKey key)
  51. {
  52. NavigateToNode(key);
  53. int index = GetIndexOf(key);
  54. if (index < 0)
  55. return false;
  56. if (!RemoveUnlessOverflow(index))
  57. {
  58. //ToDo:SplitAndThenRemove
  59. throw new NotImplementedException();
  60. }
  61. if (ValidBytes > m_minRecordNodeBytes) //if the node has not underflowed, we can exit early.
  62. return true;
  63. if (IsRightSiblingIndexNull && IsLeftSiblingIndexNull) //If there are no nodes to combine with, we can quit early.
  64. return true;
  65. if (RecordCount > 0 && (IsRightSiblingIndexNull || IsLeftSiblingIndexNull)) //There can be fewer than the minimum it is the first or last node on the level.
  66. return true;
  67. bool canCombineWithLeft;
  68. bool canCombineWithRight;
  69. SparseIndex.CanCombineWithSiblings(LowerKey, (byte)(Level + 1), out canCombineWithLeft, out canCombineWithRight);
  70. if (RecordCount == 0) //Only will occur if the right or left node is empty (but not both)
  71. {
  72. if (canCombineWithLeft && IsRightSiblingIndexNull)
  73. CombineNodes(LeftSiblingNodeIndex, NodeIndex);
  74. else if (canCombineWithRight && IsLeftSiblingIndexNull)
  75. CombineNodes(NodeIndex, RightSiblingNodeIndex);
  76. else
  77. throw new Exception("Should never reach this condition");
  78. return true;
  79. }
  80. int deltaBytesWhenCombining = MaxOverheadWithCombineNodes - HeaderSize;
  81. if (IsRightSiblingIndexNull) //We can only combine with the left node.
  82. {
  83. if (!canCombineWithLeft)
  84. throw new Exception("Should never reach this condition");
  85. if (ValidBytes + GetValidBytes(LeftSiblingNodeIndex) + deltaBytesWhenCombining < BlockSize)
  86. CombineNodes(LeftSiblingNodeIndex, NodeIndex);
  87. else
  88. RebalanceNodes(LeftSiblingNodeIndex, NodeIndex);
  89. }
  90. else if (IsLeftSiblingIndexNull) //We can only combine with the right node.
  91. {
  92. if (!canCombineWithRight)
  93. throw new Exception("Should never reach this condition");
  94. if (ValidBytes + GetValidBytes(RightSiblingNodeIndex) + deltaBytesWhenCombining < BlockSize)
  95. CombineNodes(NodeIndex, RightSiblingNodeIndex);
  96. else
  97. RebalanceNodes(NodeIndex, RightSiblingNodeIndex);
  98. }
  99. else //I can combine with the right or the left node
  100. {
  101. if (canCombineWithLeft && ValidBytes + GetValidBytes(LeftSiblingNodeIndex) + deltaBytesWhenCombining < BlockSize)
  102. CombineNodes(LeftSiblingNodeIndex, NodeIndex);
  103. else if (canCombineWithRight && ValidBytes + GetValidBytes(RightSiblingNodeIndex) + deltaBytesWhenCombining < BlockSize)
  104. CombineNodes(NodeIndex, RightSiblingNodeIndex);
  105. else if (canCombineWithLeft)
  106. RebalanceNodes(LeftSiblingNodeIndex, NodeIndex);
  107. else if (canCombineWithRight)
  108. RebalanceNodes(NodeIndex, RightSiblingNodeIndex);
  109. else
  110. throw new Exception("Should never reach this condition");
  111. }
  112. return true;
  113. }
  114. //ToDO: Checked
  115. private void RebalanceNodes(uint leftNode, uint rightNode)
  116. {
  117. Clear();
  118. Node<TKey> left = m_tempNode1;
  119. Node<TKey> right = m_tempNode2;
  120. left.Clear();
  121. right.Clear();
  122. left.SetNodeIndex(leftNode);
  123. right.SetNodeIndex(rightNode);
  124. int averageSize = (left.ValidBytes + (int)right.ValidBytes) >> 1;
  125. if (left.ValidBytes < right.ValidBytes)
  126. {
  127. //Transfer records from Right to Left
  128. TransferRecordsFromRightToLeft(left, right, averageSize - left.ValidBytes);
  129. UpdateBoundsOfNode(left, right);
  130. }
  131. else
  132. {
  133. //Transfer records from Left to Right
  134. TransferRecordsFromLeftToRight(left, right, averageSize - right.ValidBytes);
  135. UpdateBoundsOfNode(left, right);
  136. }
  137. }
  138. private void CombineNodes(uint leftNode, uint rightNode)
  139. {
  140. Clear();
  141. Node<TKey> left = m_tempNode1;
  142. Node<TKey> right = m_tempNode2;
  143. left.Clear();
  144. right.Clear();
  145. left.SetNodeIndex(leftNode);
  146. right.SetNodeIndex(rightNode);
  147. //Bug: Valid Bytes includes the header. Figure out why this does not cause a bug.
  148. if (left.RecordCount == 0)
  149. {
  150. TransferRecordsFromLeftToRight(left, right, left.ValidBytes);
  151. UpdateBoundsAndRemoveEmptyNode(left, right);
  152. }
  153. else if (right.RecordCount == 0)
  154. {
  155. TransferRecordsFromRightToLeft(left, right, right.ValidBytes);
  156. UpdateBoundsAndRemoveEmptyNode(left, right);
  157. }
  158. else
  159. {
  160. TransferRecordsFromRightToLeft(left, right, right.ValidBytes);
  161. UpdateBoundsAndRemoveEmptyNode(left, right);
  162. }
  163. }
  164. private void UpdateBoundsOfNode(Node<TKey> leftNode, Node<TKey> rightNode)
  165. {
  166. TKey oldLowerKey = new TKey();
  167. TKey newLowerKey = new TKey();
  168. KeyMethods.Copy(rightNode.LowerKey, oldLowerKey);
  169. KeyMethods.Read(rightNode.GetReadPointerAfterHeader(), newLowerKey); //ToDo: Make Generic
  170. rightNode.LowerKey = newLowerKey;
  171. leftNode.UpperKey = newLowerKey;
  172. SparseIndex.UpdateKey(oldLowerKey, newLowerKey, (byte)(Level + 1));
  173. }
  174. private void UpdateBoundsAndRemoveEmptyNode(Node<TKey> leftNode, Node<TKey> rightNode)
  175. {
  176. if (leftNode.RecordCount == 0) //Remove the left node
  177. {
  178. //Change the existing pointer to the left node to point to the right node.
  179. SparseIndex.UpdateValue(leftNode.LowerKey, new SortedTreeUInt32(rightNode.NodeIndex), (byte)(Level + 1));
  180. //Now remove the unused key position
  181. SparseIndex.Remove(rightNode.LowerKey, (byte)(Level + 1));
  182. rightNode.LowerKey = leftNode.LowerKey;
  183. rightNode.LeftSiblingNodeIndex = leftNode.LeftSiblingNodeIndex;
  184. if (leftNode.LeftSiblingNodeIndex != uint.MaxValue)
  185. {
  186. leftNode.SeekToLeftSibling();
  187. leftNode.RightSiblingNodeIndex = rightNode.NodeIndex;
  188. }
  189. }
  190. else if (rightNode.RecordCount == 0) //Remove the right node.
  191. {
  192. SparseIndex.Remove(rightNode.LowerKey, (byte)(Level + 1));
  193. leftNode.UpperKey = rightNode.UpperKey;
  194. leftNode.RightSiblingNodeIndex = rightNode.RightSiblingNodeIndex;
  195. if (rightNode.RightSiblingNodeIndex != uint.MaxValue)
  196. {
  197. rightNode.SeekToRightSibling();
  198. rightNode.LeftSiblingNodeIndex = leftNode.NodeIndex;
  199. }
  200. }
  201. else
  202. {
  203. throw new Exception("Should never get here");
  204. }
  205. }
  206. }
  207. }