RbTree.cs 81 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026
  1. //------------------------------------------------------------------------------
  2. // <copyright file="Selection.cs" company="Microsoft">
  3. // Copyright (c) Microsoft Corporation. All rights reserved.
  4. // </copyright>
  5. // <owner current="true" primary="true">[....]</owner>
  6. // <owner current="true" primary="false">[....]</owner>
  7. //------------------------------------------------------------------------------
  8. #if DEBUG
  9. //#define VerifyIndex
  10. #define VerifyPath
  11. #define VerifySort
  12. #endif
  13. namespace System.Data
  14. {
  15. using System;
  16. using System.Collections;
  17. using System.Data.Common;
  18. using System.Diagnostics;
  19. internal enum RBTreeError {
  20. InvalidPageSize = 1,
  21. // InvalidCompareDelegate = 2,
  22. PagePositionInSlotInUse = 3,
  23. NoFreeSlots = 4,
  24. InvalidStateinInsert = 5,
  25. // InvalidStateinEndInsert = 6,
  26. InvalidNextSizeInDelete = 7,
  27. InvalidStateinDelete = 8,
  28. InvalidNodeSizeinDelete = 9,
  29. InvalidStateinEndDelete = 10,
  30. CannotRotateInvalidsuccessorNodeinDelete = 11,
  31. // IndexOutOfRange = 12,
  32. IndexOutOFRangeinGetNodeByIndex = 13,
  33. RBDeleteFixup = 14,
  34. UnsupportedAccessMethod1 = 15,
  35. UnsupportedAccessMethod2 = 16,
  36. UnsupportedAccessMethodInNonNillRootSubtree = 17,
  37. AttachedNodeWithZerorbTreeNodeId = 18, // DataRowCollection
  38. CompareNodeInDataRowTree = 19, // DataRowCollection
  39. CompareSateliteTreeNodeInDataRowTree = 20, // DataRowCollection
  40. NestedSatelliteTreeEnumerator = 21,
  41. }
  42. internal enum TreeAccessMethod{
  43. KEY_SEARCH_AND_INDEX = 1,
  44. INDEX_ONLY = 2,
  45. }
  46. // an index represents location the tree
  47. // a tree has an array of pages (max 2^16) (top 16 bits)
  48. // a page has an array of nodes (max 2^16) (bottom 16 bits)
  49. // nodes are indexed by RBTree.PageTable[index>>16].Slots[index&0xFFFF]
  50. // a tree has an PageTableBitmap to indicate which allocated pages have free nodes
  51. // a page has a SlotBitmap to indicate which slots are free
  52. // intial page allocation (assuming no deletes)
  53. // #page * #slot = #total, #cumulative
  54. // ( 4) * 32 = 128, 127 (subtract 1 for NIL node)
  55. // ( 32 - 4) * 256 = 7168, 7,295
  56. // ( 128 - 32) * 1024 = 98304, 105,599
  57. // ( 4096 - 128) * 4096 = 16252928, 16,358,527
  58. // (32768 - 4096) * 8192 = 234881024, 251,239,551
  59. // (65535 - 32768) * 65536 = 2147418112, 2,398,657,663 (excess nodes 251,174,016 > Int32.MaxValue)
  60. // tree page size is GetIntValueFromBitMap(inUsePageCount) // return highest bit in array
  61. //private static readonly int[] PageSize = new int[17] { // nobit + 16 bits == 17 position
  62. // 32, 32, 32, // inUsePageCount < 4 0, 1, 2,
  63. // 256, 256, 256, // inUsePageCount < 32 4, 8, 16,
  64. // 1024, 1024, // inUsePageCount < 128 32, 64,
  65. // 4096, 4096, 4096, 4096, 4096, // inUsePageCount < 4096 128, 256, 512, 1024, 2048,
  66. // 8192, 8192, 8192, // inUsePageCount < 32768 4096, 8192, 16384
  67. // 65535 // inUsePageCount <= 65535
  68. //};
  69. // the in-ordering of nodes in the tree (the second graph has duplicate nodes)
  70. // for the satellite tree, the main tree node is the clone, GetNodeByIndex always returns the satelliteRootid
  71. // 4 | 4
  72. // / \ | / \
  73. // 2 6 | 3 - 3 7
  74. // / \ / \ | / \ / \ / \
  75. // 1 3 5 7 | 1 5 2 4 8 9
  76. // PageTable (starting at 32) doubles in size on demand (^16 - ^5 = 11 grows to reach max PageTable size)
  77. // if a page has no allocated slots, it will be dropped
  78. // worst case scenario is to repeatedly add/remove on a boundary condition
  79. // the primary change to support Index using Predicate<DataRow> or Comparison<DataRow> was to eliminate all
  80. // unnecessary searching for the node in the main tree when operating on a node in the satellite branch
  81. // in all cases except GetNodeByKey(K)& GetIndexByNode(int), we know what that mainTreeNodeID is and can avoid searching
  82. internal abstract class RBTree<K> : System.Collections.IEnumerable {
  83. // 2^16 #pages * 2^n == total number of nodes. 512 = 32 million, 1024 = 64 million, 2048 = 128m, 4096=256m, 8192=512m, 16284=1 billion
  84. // 32K=2 billion.
  85. internal const int DefaultPageSize = 32; /* 512 = 2^9 32 million nodes*/
  86. internal const int NIL = 0; // 0th page, 0th slot for each tree till CLR static & generics issue is fixed
  87. private TreePage[] _pageTable; // initial size 4, then doubles (grows) - it never shrinks
  88. private Int32[] _pageTableMap;
  89. private int _inUsePageCount = 0; // contains count of allocated pages per tree, its <= the capacity of pageTable
  90. private int nextFreePageLine; // used for keeping track of position of last used free page in pageTable
  91. public int root;
  92. private int _version;
  93. private int _inUseNodeCount = 0; // total number of nodes currently in use by this tree.
  94. private int _inUseSatelliteTreeCount = 0; // total number of satellite associated with this tree.
  95. private readonly TreeAccessMethod _accessMethod;
  96. protected abstract int CompareNode (K record1, K record2);
  97. protected abstract int CompareSateliteTreeNode (K record1, K record2);
  98. protected RBTree (TreeAccessMethod accessMethod) {
  99. _accessMethod = accessMethod;
  100. InitTree();
  101. }
  102. private void InitTree() {
  103. root = NIL;
  104. _pageTable = new TreePage[1 * TreePage.slotLineSize];
  105. _pageTableMap = new Int32[(_pageTable.Length + TreePage.slotLineSize - 1) / TreePage.slotLineSize]; // Ceiling(size)
  106. _inUsePageCount = 0;
  107. nextFreePageLine = 0;
  108. AllocPage (DefaultPageSize);
  109. // alloc storage for reserved NIL node. segment 0, slot 0; Initialize NIL
  110. _pageTable[0].Slots[0].nodeColor = NodeColor.black;
  111. _pageTable[0].SlotMap[0] = 0x1;
  112. _pageTable[0].InUseCount = 1;
  113. _inUseNodeCount = 1;
  114. _inUseSatelliteTreeCount = 0; // total number of satellite associated with this tree.
  115. }
  116. private void FreePage (TreePage page)
  117. {
  118. MarkPageFree (page);
  119. _pageTable[page.PageId] = null;
  120. _inUsePageCount--;
  121. }
  122. /* AllocPage()
  123. * size : Allocates a page of the specified size.
  124. *
  125. * Look for an unallocated page entry.
  126. * (1) If entry for an unallocated page exists in current pageTable - use it
  127. * (2) else extend pageTable
  128. */
  129. private TreePage AllocPage (int size)
  130. {
  131. int freePageIndex = GetIndexOfPageWithFreeSlot (false);
  132. if (freePageIndex != -1)
  133. {
  134. _pageTable[freePageIndex] = new TreePage (size);
  135. nextFreePageLine = freePageIndex / TreePage.slotLineSize;
  136. }
  137. else
  138. {
  139. // no free position found, increase pageTable size
  140. TreePage[] newPageTable = new TreePage[_pageTable.Length * 2];
  141. System.Array.Copy (_pageTable, 0, newPageTable, 0, _pageTable.Length);
  142. Int32[] newPageTableMap = new Int32[(newPageTable.Length + TreePage.slotLineSize - 1) / TreePage.slotLineSize];
  143. System.Array.Copy (_pageTableMap, 0, newPageTableMap, 0, _pageTableMap.Length);
  144. nextFreePageLine = _pageTableMap.Length;
  145. freePageIndex = _pageTable.Length;
  146. _pageTable = newPageTable;
  147. _pageTableMap = newPageTableMap;
  148. _pageTable[freePageIndex] = new TreePage (size);
  149. }
  150. _pageTable[freePageIndex].PageId = freePageIndex;
  151. _inUsePageCount++;
  152. return _pageTable[freePageIndex];
  153. }
  154. /* MarkPageFull()
  155. * Mark the specified page "Full" as all its slots aer in use
  156. */
  157. private void MarkPageFull (TreePage page)
  158. {
  159. // set bit associated with page to mark it as full
  160. /*
  161. int pageTableMapIndex = (page.PageId / TreePage.slotLineSize);
  162. int pageTableMapOffset = (page.PageId % TreePage.slotLineSize);
  163. Int32 pageBitMask = ((Int32)1) << pageTableMapOffset;
  164. _pageTableMap[pageTableMapIndex] |= (pageBitMask);
  165. */
  166. _pageTableMap[page.PageId / TreePage.slotLineSize] |= (1 << (page.PageId % TreePage.slotLineSize));
  167. }
  168. /* MarkPageFree()
  169. * Mark the specified page as "Free". It has atleast 1 available slot.
  170. */
  171. private void MarkPageFree (TreePage page)
  172. {
  173. // set bit associated with page to mark it as free
  174. /*
  175. int pageTableMapIndex = (page.PageId / TreePage.slotLineSize);
  176. int pageTableMapOffset = (page.PageId % TreePage.slotLineSize);
  177. Int32 pageBitMask = ((Int32)1) << pageTableMapOffset;
  178. _pageTableMap[pageTableMapIndex] &= ~(pageBitMask);
  179. */
  180. _pageTableMap[page.PageId / TreePage.slotLineSize] &= ~(1 << (page.PageId % TreePage.slotLineSize));
  181. }
  182. private static int GetIntValueFromBitMap (UInt32 bitMap)
  183. {
  184. Int32 value = 0; // 0 based slot position
  185. /*
  186. * Assumption: bitMap can have max, exactly 1 bit set.
  187. * convert bitMap to int value giving number of 0's to its right
  188. * return value between 0 and 31
  189. */
  190. if ((bitMap & 0xFFFF0000) != 0)
  191. {
  192. value += 16;
  193. bitMap >>=16;
  194. }
  195. if ((bitMap & 0x0000FF00) != 0)
  196. {
  197. value += 8;
  198. bitMap >>=8;
  199. }
  200. if ((bitMap & 0x000000F0) != 0)
  201. {
  202. value += 4;
  203. bitMap >>=4;
  204. }
  205. if ((bitMap & 0x0000000C) != 0)
  206. {
  207. value += 2;
  208. bitMap >>=2;
  209. }
  210. if ((bitMap & 0x00000002) != 0)
  211. value += 1;
  212. return value;
  213. }
  214. /*
  215. * FreeNode()
  216. * nodeId: The nodeId of the node to be freed
  217. */
  218. private void FreeNode (int nodeId)
  219. {
  220. TreePage page = _pageTable[nodeId >> 16];
  221. int slotIndex = nodeId & 0xFFFF;
  222. page.Slots[slotIndex] = default(Node);
  223. // clear slotMap entry associated with nodeId
  224. page.SlotMap[slotIndex / TreePage.slotLineSize] &= ~( ((Int32)1) << (int)(slotIndex % TreePage.slotLineSize));
  225. page.InUseCount--;
  226. _inUseNodeCount--;
  227. if (page.InUseCount == 0)
  228. FreePage (page);
  229. else if (page.InUseCount == page.Slots.Length - 1)
  230. MarkPageFree (page); // With freeing of a node, a previous full page has a free slot.
  231. }
  232. /*
  233. * GetIndexOfPageWithFreeSlot()
  234. * allocatedPage: If true, look for an allocatedPage with free slot else look for an unallocated page entry in pageTable
  235. * return: if allocatedPage is true, return index of a page with at least 1 free slot
  236. * else return index of an unallocated page, pageTable[index] is empty.
  237. */
  238. private int GetIndexOfPageWithFreeSlot (bool allocatedPage)
  239. {
  240. int pageTableMapPos = nextFreePageLine;
  241. int pageIndex = -1;
  242. while (pageTableMapPos < _pageTableMap.Length)
  243. {
  244. if (((UInt32)_pageTableMap[pageTableMapPos]) < 0xFFFFFFFF)
  245. {
  246. UInt32 pageSegmentMap = (UInt32)_pageTableMap[pageTableMapPos];
  247. while ((pageSegmentMap ^ (0xFFFFFFFF)) != 0) //atleast one "0" is there (same as <0xFFFFFFFF)
  248. {
  249. UInt32 pageWithFreeSlot = (UInt32)((~(pageSegmentMap)) & (pageSegmentMap + 1));
  250. //
  251. if ((_pageTableMap[pageTableMapPos] & pageWithFreeSlot) != 0) //paranoia check
  252. throw ExceptionBuilder.InternalRBTreeError(RBTreeError.PagePositionInSlotInUse);
  253. pageIndex = (pageTableMapPos * TreePage.slotLineSize) + GetIntValueFromBitMap (pageWithFreeSlot); // segment + offset
  254. if (allocatedPage)
  255. {
  256. if (_pageTable[pageIndex] != null)
  257. return pageIndex;
  258. }
  259. else
  260. {
  261. if (_pageTable[pageIndex] == null)
  262. return pageIndex; // pageIndex points to an unallocated Page
  263. }
  264. pageIndex = -1;
  265. pageSegmentMap |= pageWithFreeSlot; // found "reset bit", but unallocated page, mark it as unavaiable and continue search
  266. }
  267. }
  268. pageTableMapPos++;
  269. }
  270. if (nextFreePageLine != 0)
  271. {
  272. //Try one more time, starting from 0th page segment position to locate a page with free slots
  273. nextFreePageLine = 0;
  274. pageIndex = GetIndexOfPageWithFreeSlot (allocatedPage);
  275. }
  276. return pageIndex;
  277. }
  278. public int Count {
  279. get {
  280. Debug.Assert(_inUseNodeCount-1 == SubTreeSize(root), "count mismatch");
  281. return (_inUseNodeCount-1);
  282. }
  283. }
  284. public bool HasDuplicates {
  285. get {
  286. return (0 != _inUseSatelliteTreeCount);
  287. }
  288. }
  289. /*
  290. * GetNewNode()
  291. * Allocate storage for a new node and assign in the specified key.
  292. *
  293. * Find a page with free slots or allocate a new page.
  294. * Use bitmap associated with page to allocate a slot.
  295. * mark the slot as used and return its index.
  296. */
  297. private int GetNewNode (K key)
  298. {
  299. // find page with free slots, if none, allocate a new page
  300. TreePage page = null;
  301. int freePageIndex = GetIndexOfPageWithFreeSlot (true);
  302. if (freePageIndex != -1)
  303. page = _pageTable[freePageIndex];
  304. else if (_inUsePageCount < (4))
  305. page = AllocPage (DefaultPageSize); // First 128 slots
  306. else if (_inUsePageCount < (32))
  307. page = AllocPage (256);
  308. else if (_inUsePageCount < (128))
  309. page = AllocPage (1024);
  310. else if (_inUsePageCount < (4096))
  311. page = AllocPage (4096);
  312. else if (_inUsePageCount < (32*1024))
  313. page = AllocPage (8192); // approximately First 16 million slots (2^24)
  314. else
  315. page = AllocPage (64*1024); // Page size to accomodate more than 16 million slots (Max 2 Billion and 16 million slots)
  316. // page contains atleast 1 free slot.
  317. int slotId = page.AllocSlot (this);
  318. //
  319. if (slotId == -1)
  320. throw ExceptionBuilder.InternalRBTreeError(RBTreeError.NoFreeSlots);
  321. // NodeId: Upper 16 bits pageId, lower bits slotId
  322. page.Slots[slotId].selfId = (int)(((UInt32)page.PageId) << 16) | slotId;
  323. Debug.Assert(page.Slots[slotId].leftId == NIL, "node not cleared");
  324. Debug.Assert(page.Slots[slotId].rightId == NIL, "node not cleared");
  325. Debug.Assert(page.Slots[slotId].parentId == NIL, "node not cleared");
  326. Debug.Assert(page.Slots[slotId].nextId == NIL, "node not cleared");
  327. page.Slots[slotId].subTreeSize = 1; // new Nodes have size 1.
  328. page.Slots[slotId].keyOfNode = key;
  329. Debug.Assert(page.Slots[slotId].nodeColor == NodeColor.red, "node not cleared");
  330. return page.Slots[slotId].selfId;
  331. }
  332. private int Successor (int x_id)
  333. {
  334. if (Right (x_id) != NIL)
  335. return Minimum (Right (x_id)); //return left most node in right sub-tree.
  336. int y_id = Parent (x_id);
  337. while (y_id != NIL && x_id == Right (y_id))
  338. {
  339. x_id = y_id;
  340. y_id = Parent (y_id);
  341. }
  342. return y_id;
  343. }
  344. private bool Successor(ref int nodeId, ref int mainTreeNodeId)
  345. {
  346. if (NIL == nodeId)
  347. { // find first node, using branchNodeId as the root
  348. nodeId = Minimum(mainTreeNodeId);
  349. mainTreeNodeId = NIL;
  350. }
  351. else
  352. { // find next node
  353. nodeId = Successor(nodeId);
  354. if ((NIL == nodeId) && (NIL != mainTreeNodeId))
  355. { // done with satellite branch, move back to main tree
  356. nodeId = Successor(mainTreeNodeId);
  357. mainTreeNodeId = NIL;
  358. }
  359. }
  360. if (NIL != nodeId)
  361. { // test for satellite branch
  362. if (NIL != Next(nodeId))
  363. { // find first node of satellite branch
  364. if (NIL != mainTreeNodeId)
  365. { // satellite branch has satellite branch - very bad
  366. throw ExceptionBuilder.InternalRBTreeError(RBTreeError.NestedSatelliteTreeEnumerator);
  367. }
  368. mainTreeNodeId = nodeId;
  369. nodeId = Minimum(Next(nodeId));
  370. }
  371. // has value
  372. return true;
  373. }
  374. // else no value, done with main tree
  375. return false;
  376. }
  377. private int Minimum (int x_id)
  378. {
  379. while (Left (x_id) != NIL) {
  380. x_id = Left (x_id);
  381. }
  382. return x_id;
  383. }
  384. /*
  385. * LeftRotate()
  386. *
  387. * It returns the node id for the root of the rotated tree
  388. */
  389. private int LeftRotate (int root_id, int x_id, int mainTreeNode)
  390. {
  391. int y_id = Right (x_id);
  392. // Turn y's left subtree into x's right subtree
  393. SetRight (x_id, Left (y_id));
  394. if (Left (y_id) != NIL) {
  395. SetParent (Left (y_id), x_id);
  396. }
  397. SetParent (y_id, Parent (x_id));
  398. if (Parent (x_id) == NIL) {
  399. if (root_id == NIL) {
  400. root = y_id;
  401. }
  402. else {
  403. SetNext (mainTreeNode, y_id);
  404. SetKey (mainTreeNode, Key (y_id));
  405. root_id = y_id;
  406. }
  407. }
  408. else if (x_id == Left (Parent (x_id))) { // x is left child of its parent
  409. SetLeft (Parent (x_id), y_id);
  410. }
  411. else {
  412. SetRight (Parent (x_id), y_id);
  413. }
  414. SetLeft (y_id, x_id);
  415. SetParent (x_id, y_id);
  416. //maintain size: y_id = parent & x_id == child
  417. if (x_id != NIL) {
  418. SetSubTreeSize(x_id, (SubTreeSize(Left(x_id)) + SubTreeSize(Right(x_id)) + (Next(x_id) == NIL ? 1 : SubTreeSize(Next(x_id)))));
  419. }
  420. if (y_id != NIL) {
  421. SetSubTreeSize(y_id, (SubTreeSize(Left(y_id)) + SubTreeSize(Right(y_id)) + (Next(y_id) == NIL ? 1 : SubTreeSize(Next(y_id)))));
  422. }
  423. return root_id;
  424. }
  425. /*
  426. * RightRotate()
  427. *
  428. * It returns the node id for the root of the rotated tree
  429. */
  430. private int RightRotate (int root_id, int x_id, int mainTreeNode)
  431. {
  432. int y_id = Left (x_id);
  433. SetLeft (x_id, Right (y_id)); // Turn y's right subtree into x's left subtree
  434. if (Right (y_id) != NIL) {
  435. SetParent (Right (y_id), x_id);
  436. }
  437. SetParent (y_id, Parent (x_id));
  438. if (Parent (x_id) == NIL) {
  439. if (root_id == NIL) {
  440. root = y_id;
  441. }
  442. else {
  443. SetNext (mainTreeNode, y_id);
  444. SetKey (mainTreeNode, Key (y_id));
  445. root_id = y_id;
  446. }
  447. }
  448. else if (x_id == Left (Parent (x_id))) // x is left child of its parent
  449. SetLeft (Parent (x_id), y_id);
  450. else
  451. SetRight (Parent (x_id), y_id);
  452. SetRight (y_id, x_id);
  453. SetParent (x_id, y_id);
  454. //maintain size: y_id == parent && x_id == child.
  455. if (x_id != NIL) {
  456. SetSubTreeSize(x_id, (SubTreeSize(Left(x_id)) + SubTreeSize(Right(x_id)) + (Next(x_id) == NIL ? 1 : SubTreeSize(Next(x_id)))));
  457. }
  458. if (y_id != NIL) {
  459. SetSubTreeSize(y_id, (SubTreeSize(Left(y_id)) + SubTreeSize(Right(y_id)) + (Next(y_id) == NIL ? 1 : SubTreeSize(Next(y_id)))));
  460. }
  461. return root_id;
  462. }
  463. #if VerifySort
  464. // This helps validate the sorting of the tree to help catch instances of corruption much sooner.
  465. // corruption happens when the data changes without telling the tree or when multi-threads do simultanous write operations
  466. private int Compare(int root_id, int x_id, int z_id) {
  467. Debug.Assert(NIL != x_id, "nil left");
  468. Debug.Assert(NIL != z_id, "nil right");
  469. return (root_id == NIL) ? CompareNode (Key (x_id), Key (z_id)) : CompareSateliteTreeNode (Key (x_id), Key (z_id));
  470. }
  471. #endif
  472. /*
  473. * RBInsert()
  474. * root_id: root_id of the tree to which a node has to be inserted. it is NIL for inserting to Main tree.
  475. * x_id : node_id of node to be inserted
  476. *
  477. * returns: The root of the tree to which the specified node was added. its NIL if the node was added to Main RBTree.
  478. *
  479. * if root_id is NIL -> use CompareNode else use CompareSateliteTreeNode
  480. *
  481. * Satelite tree creation:
  482. * First Duplicate value encountered. Create a *new* tree whose root will have the same key value as the current node.
  483. * The Duplicate tree nodes have same key when used with CompareRecords but distinct record ids.
  484. * The current record at all times will have the same *key* as the duplicate tree root.
  485. */
  486. private int RBInsert (int root_id, int x_id, int mainTreeNodeID, int position, bool append)
  487. {
  488. unchecked{_version++;}
  489. // Insert Node x at the appropriate position
  490. int y_id = NIL;
  491. int z_id = (root_id == NIL) ? root : root_id; //if non NIL, then use the specifid root_id as tree's root.
  492. if (_accessMethod == TreeAccessMethod.KEY_SEARCH_AND_INDEX && !append)
  493. {
  494. Debug.Assert(-1 == position, "KEY_SEARCH_AND_INDEX with bad position");
  495. while (z_id != NIL) // in-order traverse and find node with a NILL left or right child
  496. {
  497. IncreaseSize (z_id);
  498. y_id = z_id; // y_id set to the proposed parent of x_id
  499. int c = (root_id == NIL) ? CompareNode (Key (x_id), Key (z_id)) : CompareSateliteTreeNode (Key (x_id), Key (z_id));
  500. if (c < 0) {
  501. #if VerifySort
  502. Debug.Assert((NIL == Left(z_id)) || (0 > Compare(root_id, Left(z_id), z_id)), "Left is not left");
  503. #endif
  504. z_id = Left (z_id);
  505. }
  506. else if (c > 0) {
  507. #if VerifySort
  508. Debug.Assert((NIL == Right(z_id)) || (0 < Compare(root_id, Right(z_id), z_id)), "Right is not right");
  509. #endif
  510. z_id = Right (z_id);
  511. }
  512. else {
  513. // Multiple records with same key - insert it to the duplicate record tree associated with current node
  514. if (root_id != NIL) {
  515. throw ExceptionBuilder.InternalRBTreeError(RBTreeError.InvalidStateinInsert);
  516. }
  517. if (Next(z_id) != NIL) {
  518. root_id = RBInsert (Next (z_id), x_id, z_id, -1, false); // z_id is existing mainTreeNodeID
  519. SetKey (z_id, Key (Next (z_id)));
  520. #if VerifyPath
  521. (new NodePath(x_id, z_id)).VerifyPath(this); // verify x_id after its been added
  522. #endif
  523. }
  524. else {
  525. int newMainTreeNodeId = NIL;
  526. // The existing node is pushed into the Satellite Tree and a new Node
  527. // is created in the main tree, whose's next points to satellite root.
  528. newMainTreeNodeId = GetNewNode (Key (z_id));
  529. _inUseSatelliteTreeCount++;
  530. // copy contents of z_id to dupRootId (main tree node).
  531. SetNext(newMainTreeNodeId, z_id);
  532. SetColor(newMainTreeNodeId, color(z_id));
  533. SetParent(newMainTreeNodeId, Parent(z_id));
  534. SetLeft(newMainTreeNodeId, Left(z_id));
  535. SetRight(newMainTreeNodeId, Right(z_id));
  536. // Update z_id's non-nil parent
  537. if( Left(Parent(z_id))==z_id)
  538. SetLeft(Parent(z_id), newMainTreeNodeId);
  539. else if (Right(Parent(z_id))==z_id)
  540. SetRight(Parent(z_id), newMainTreeNodeId);
  541. // update children.
  542. if (Left(z_id) != NIL)
  543. SetParent(Left(z_id), newMainTreeNodeId);
  544. if (Right(z_id) != NIL)
  545. SetParent(Right(z_id), newMainTreeNodeId);
  546. if (root == z_id)
  547. root = newMainTreeNodeId;
  548. // Reset z_id's pointers to NIL. It will start as the satellite tree's root.
  549. SetColor(z_id, NodeColor.black);
  550. SetParent(z_id, NIL);
  551. SetLeft(z_id, NIL);
  552. SetRight(z_id, NIL);
  553. int savedSize = SubTreeSize(z_id);
  554. SetSubTreeSize(z_id, 1);
  555. // With z_id as satellite root, insert x_id
  556. root_id = RBInsert (z_id, x_id, newMainTreeNodeId, -1, false);
  557. SetSubTreeSize(newMainTreeNodeId, savedSize);
  558. #if VerifyPath
  559. (new NodePath(x_id, newMainTreeNodeId)).VerifyPath(this); // verify x_id after its been added
  560. #endif
  561. }
  562. return root_id;
  563. }
  564. }
  565. }
  566. else if (_accessMethod == TreeAccessMethod.INDEX_ONLY || append)
  567. {
  568. if (position == -1) {
  569. position = SubTreeSize(root); // append
  570. }
  571. while (z_id != NIL) // in-order traverse and find node with a NILL left or right child
  572. {
  573. IncreaseSize (z_id);
  574. y_id = z_id; // y_id set to the proposed parent of x_id
  575. //int c = (SubTreeSize(y_id)-(position)); // Actually it should be: SubTreeSize(y_id)+1 - (position + 1)
  576. int c = (position) - (SubTreeSize(Left(y_id)));
  577. if (c <= 0) {
  578. z_id = Left (z_id);
  579. }
  580. else {
  581. //position = position - SubTreeSize(z_id);
  582. z_id = Right (z_id);
  583. if (z_id != NIL) {
  584. position = c-1; //skip computation of position for leaf node
  585. }
  586. }
  587. }
  588. }
  589. else {
  590. throw ExceptionBuilder.InternalRBTreeError(RBTreeError.UnsupportedAccessMethod1);
  591. }
  592. SetParent (x_id, y_id);
  593. if (y_id == NIL)
  594. {
  595. if (root_id == NIL) {
  596. root = x_id;
  597. }
  598. else
  599. {
  600. // technically we should never come here. Satellite tree always has a root and atleast 1 child.
  601. // if it has only root as it's node, then the satellite tree gets collapsed into the main tree.
  602. #if VerifyPath
  603. (new NodePath(x_id, mainTreeNodeID)).VerifyPath(this); // verify x_id after its been added
  604. #endif
  605. SetNext(mainTreeNodeID, x_id);
  606. SetKey(mainTreeNodeID, Key(x_id));
  607. root_id = x_id;
  608. }
  609. }
  610. else
  611. {
  612. int c=0;
  613. if (_accessMethod == TreeAccessMethod.KEY_SEARCH_AND_INDEX)
  614. c = (root_id == NIL) ? CompareNode (Key(x_id), Key(y_id)) : CompareSateliteTreeNode (Key (x_id), Key (y_id));
  615. else if (_accessMethod == TreeAccessMethod.INDEX_ONLY)
  616. c = (position <= 0) ? -1 : 1;
  617. else {
  618. throw ExceptionBuilder.InternalRBTreeError(RBTreeError.UnsupportedAccessMethod2);
  619. }
  620. if (c < 0)
  621. SetLeft (y_id, x_id);
  622. else
  623. SetRight (y_id, x_id);
  624. }
  625. SetLeft (x_id, NIL);
  626. SetRight (x_id, NIL);
  627. SetColor (x_id, NodeColor.red);
  628. z_id = x_id; // for verification later
  629. // fix the tree
  630. while (color (Parent (x_id)) == NodeColor.red)
  631. {
  632. if (Parent (x_id) == Left (Parent (Parent (x_id)))) // if x.parent is a left child
  633. {
  634. y_id = Right (Parent (Parent (x_id))); // x.parent.parent.right;
  635. if (color (y_id) == NodeColor.red) // my right uncle is red
  636. {
  637. SetColor (Parent (x_id), NodeColor.black); // x.parent.color = Color.black;
  638. SetColor (y_id, NodeColor.black);
  639. SetColor (Parent (Parent (x_id)), NodeColor.red); // x.parent.parent.color = Color.red;
  640. x_id = Parent (Parent (x_id)); // x = x.parent.parent;
  641. }
  642. else
  643. { // my right uncle is black
  644. if (x_id == Right (Parent (x_id)))
  645. {
  646. x_id = Parent (x_id);
  647. root_id = LeftRotate (root_id, x_id, mainTreeNodeID);
  648. }
  649. SetColor (Parent (x_id), NodeColor.black); // x.parent.color = Color.black;
  650. SetColor (Parent (Parent (x_id)), NodeColor.red); // x.parent.parent.color = Color.red;
  651. root_id = RightRotate (root_id, Parent (Parent (x_id)), mainTreeNodeID); // RightRotate (x.parent.parent);
  652. }
  653. }
  654. else
  655. { // x.parent is a right child
  656. y_id = Left (Parent (Parent (x_id))); // y = x.parent.parent.left;
  657. if (color (y_id) == NodeColor.red) // if (y.color == Color.red) // my right uncle is red
  658. {
  659. SetColor (Parent (x_id), NodeColor.black);
  660. SetColor (y_id, NodeColor.black);
  661. SetColor (Parent (Parent (x_id)), NodeColor.red); // x.parent.parent.color = Color.red;
  662. x_id = Parent (Parent (x_id));
  663. }
  664. else
  665. {// my right uncle is black
  666. if (x_id == Left (Parent (x_id)))
  667. {
  668. x_id = Parent (x_id);
  669. root_id = RightRotate (root_id, x_id, mainTreeNodeID);
  670. }
  671. SetColor (Parent (x_id), NodeColor.black); // x.parent.color = Color.black;
  672. SetColor (Parent (Parent (x_id)), NodeColor.red); // x.parent.parent.color = Color.red;
  673. root_id = LeftRotate (root_id, Parent (Parent (x_id)), mainTreeNodeID);
  674. }
  675. }
  676. }
  677. if (root_id == NIL)
  678. SetColor (root, NodeColor.black);
  679. else
  680. SetColor (root_id, NodeColor.black);
  681. #if VerifyPath
  682. (new NodePath(z_id, mainTreeNodeID)).VerifyPath(this); // verify x_id after its been added
  683. #endif
  684. return root_id;
  685. } //Insert
  686. public void UpdateNodeKey(K currentKey, K newKey)
  687. {
  688. // swap oldRecord with NewRecord in nodeId associated with oldRecord
  689. // if the matched node is a satellite root then also change the key in the associated main tree node.
  690. NodePath x_id = GetNodeByKey (currentKey);
  691. if (Parent(x_id.NodeID) == NIL && x_id.NodeID != root) //determine if x_id is a satellite root.
  692. {
  693. #if VerifyPath
  694. x_id.VerifyPath(this);
  695. #endif
  696. SetKey(x_id.MainTreeNodeID, newKey);
  697. }
  698. SetKey (x_id.NodeID, newKey);
  699. }
  700. public K DeleteByIndex(int i)
  701. {
  702. // This check was not correct, it should have been ((uint)this.Count <= (uint)i)
  703. // Even then, the index will be checked by GetNodebyIndex which will throw either
  704. // using RowOutOfRange or InternalRBTreeError depending on _accessMethod
  705. //
  706. //if (i >= (_inUseNodeCount - 1)) {
  707. // throw ExceptionBuilder.InternalRBTreeError(RBTreeError.IndexOutOfRange);
  708. //}
  709. K key;
  710. NodePath x_id = GetNodeByIndex(i); // it'l throw if corresponding node does not exist
  711. key = Key(x_id.NodeID);
  712. RBDeleteX(NIL, x_id.NodeID, x_id.MainTreeNodeID);
  713. return key;
  714. }
  715. public int RBDelete (int z_id)
  716. {
  717. // always perform delete operation on the main tree
  718. Debug.Assert(_accessMethod == TreeAccessMethod.INDEX_ONLY, "not expecting anything else");
  719. return RBDeleteX (NIL, z_id, NIL);
  720. }
  721. /*
  722. * RBDelete()
  723. * root_id: root_id of the tree. it is NIL for Main tree.
  724. * z_id : node_id of node to be deleted
  725. *
  726. * returns: The id of the spliced node
  727. *
  728. * Case 1: Node is in main tree only (decrease size in main tree)
  729. * Case 2: Node's key is shared with a main tree node whose next is non-NIL
  730. * (decrease size in both trees)
  731. * Case 3: special case of case 2: After deletion, node leaves satelite tree with only 1 node (only root),
  732. * it should collapse the satelite tree - go to case 4. (decrease size in both trees)
  733. * Case 4: (1) Node is in Main tree and is a satelite tree root AND
  734. * (2) It is the only node in Satelite tree
  735. * (Do not decrease size in any tree, as its a collpase operation)
  736. *
  737. */
  738. private int RBDeleteX(int root_id, int z_id, int mainTreeNodeID)
  739. {
  740. int x_id = NIL; // used for holding spliced node (y_id's) child
  741. int y_id; // the spliced node
  742. int py_id; // for holding spliced node (y_id's) parent
  743. #if VerifyPath
  744. // by knowing the NodePath, when z_id is in a satellite branch we don't have to Search for mainTreeNodeID
  745. (new NodePath(z_id, mainTreeNodeID)).VerifyPath(this);
  746. #endif
  747. if (Next (z_id) != NIL)
  748. return RBDeleteX(Next(z_id), Next(z_id), z_id); // delete root of satelite tree.
  749. // if we we reach here, we are guaranteed z_id.next is NIL.
  750. bool isCase3 = false;
  751. int mNode = ((_accessMethod == TreeAccessMethod.KEY_SEARCH_AND_INDEX) ? mainTreeNodeID : z_id);
  752. if (Next (mNode) != NIL)
  753. root_id = Next (mNode);
  754. if (SubTreeSize (Next (mNode)) == 2) // Next(mNode) == root_id
  755. isCase3 = true;
  756. else if (SubTreeSize (Next (mNode)) == 1) {
  757. throw ExceptionBuilder.InternalRBTreeError(RBTreeError.InvalidNextSizeInDelete);
  758. }
  759. if (Left (z_id) == NIL || Right (z_id) == NIL)
  760. y_id = z_id;
  761. else
  762. y_id = Successor (z_id);
  763. if (Left (y_id) != NIL)
  764. x_id = Left (y_id);
  765. else
  766. x_id = Right (y_id);
  767. py_id = Parent(y_id);
  768. if (x_id != NIL)
  769. SetParent (x_id, py_id);
  770. if (py_id == NIL) // if the spliced node is the root.
  771. {
  772. // check for main tree or Satellite tree root
  773. if (root_id == NIL)
  774. root = x_id;
  775. else
  776. {
  777. // spliced node is root of satellite tree
  778. root_id = x_id;
  779. }
  780. }
  781. else if (y_id == Left (py_id)) // update y's parent to point to X as its child
  782. SetLeft (py_id, x_id);
  783. else
  784. SetRight (py_id, x_id);
  785. if (y_id != z_id)
  786. {
  787. // assign all values from y (spliced node) to z (node containing key to be deleted)
  788. // -----------
  789. SetKey (z_id, Key (y_id)); // assign all values from y to z
  790. SetNext (z_id, Next (y_id)); //z.value = y.value;
  791. }
  792. if (Next(mNode) != NIL)
  793. {
  794. // update mNode to point to satellite tree root and have the same key value.
  795. // mNode will have to be patched again after RBDeleteFixup as root_id can again change
  796. if (root_id == NIL && z_id != mNode) {
  797. throw ExceptionBuilder.InternalRBTreeError(RBTreeError.InvalidStateinDelete);
  798. }
  799. // -- it's possible for Next(mNode) to be != NIL and root_id == NIL when, the spliced node is a mNode of some
  800. // -- satellite tree and its "next" gets assigned to mNode
  801. if (root_id != NIL)
  802. {
  803. SetNext (mNode, root_id);
  804. SetKey (mNode, Key (root_id));
  805. }
  806. }
  807. // traverse from y_id's parent to root and decrement size by 1
  808. int tmp_py_id = py_id;
  809. // case: 1, 2, 3
  810. while (tmp_py_id != NIL)
  811. {
  812. //DecreaseSize (py_id, (Next(y_id)==NIL)?1:Size(Next(y_id)));
  813. RecomputeSize (tmp_py_id);
  814. tmp_py_id = Parent (tmp_py_id);
  815. }
  816. //if satelite tree node deleted, decrease size in main tree as well.
  817. if (root_id != NIL)
  818. {
  819. // case 2, 3
  820. int nodeId = mNode;
  821. while (nodeId != NIL)
  822. {
  823. DecreaseSize (nodeId);
  824. nodeId = Parent (nodeId);
  825. }
  826. }
  827. if (color (y_id) == NodeColor.black)
  828. root_id = RBDeleteFixup (root_id, x_id, py_id, mainTreeNodeID); // passing x.parent as y.parent, to handle x=Node.NIL case.
  829. if (isCase3)
  830. {
  831. // Collpase satelite tree, by swapping it with the main tree counterpart and freeing the main tree node
  832. if (mNode == NIL || SubTreeSize(Next(mNode)) != 1) {
  833. throw ExceptionBuilder.InternalRBTreeError(RBTreeError.InvalidNodeSizeinDelete);
  834. }
  835. _inUseSatelliteTreeCount--;
  836. int satelliteRootId = Next(mNode);
  837. SetLeft(satelliteRootId, Left(mNode));
  838. SetRight(satelliteRootId, Right(mNode));
  839. SetSubTreeSize(satelliteRootId, SubTreeSize(mNode));
  840. SetColor(satelliteRootId, color(mNode)); // Next of satelliteRootId is already NIL
  841. if (Parent(mNode) != NIL)
  842. {
  843. SetParent(satelliteRootId, Parent(mNode));
  844. if (Left(Parent(mNode)) == mNode) {
  845. SetLeft(Parent(mNode), satelliteRootId);
  846. }
  847. else {
  848. SetRight(Parent(mNode), satelliteRootId);
  849. }
  850. }
  851. // update mNode's children.
  852. if (Left(mNode) != NIL) {
  853. SetParent(Left(mNode), satelliteRootId);
  854. }
  855. if (Right(mNode) != NIL) {
  856. SetParent(Right(mNode), satelliteRootId);
  857. }
  858. if (root == mNode) {
  859. root = satelliteRootId;
  860. }
  861. FreeNode (mNode);
  862. mNode = NIL;
  863. }
  864. else if (Next(mNode) != NIL)
  865. {
  866. // update mNode to point to satellite tree root and have the same key value
  867. if (root_id == NIL && z_id != mNode) { //if mNode being deleted, its OK for root_id (it should be) NIL.
  868. throw ExceptionBuilder.InternalRBTreeError(RBTreeError.InvalidStateinEndDelete);
  869. }
  870. if (root_id != NIL)
  871. {
  872. SetNext (mNode, root_id);
  873. SetKey (mNode, Key (root_id));
  874. }
  875. }
  876. // In order to pin a key to it's node, free deleted z_id instead of the spliced y_id
  877. if (y_id != z_id)
  878. {
  879. // we know that key, next and value are same for z_id and y_id
  880. SetLeft (y_id, Left (z_id));
  881. SetRight (y_id, Right (z_id));
  882. SetColor (y_id, color (z_id));
  883. SetSubTreeSize (y_id, SubTreeSize(z_id));
  884. if (Parent(z_id) != NIL)
  885. {
  886. SetParent(y_id, Parent(z_id));
  887. if (Left(Parent(z_id)) == z_id) {
  888. SetLeft(Parent(z_id), y_id);
  889. }
  890. else {
  891. SetRight(Parent(z_id), y_id);
  892. }
  893. }
  894. else {
  895. SetParent(y_id, NIL);
  896. }
  897. // update children.
  898. if (Left(z_id) != NIL) {
  899. SetParent(Left(z_id), y_id);
  900. }
  901. if (Right(z_id) != NIL) {
  902. SetParent(Right(z_id), y_id);
  903. }
  904. if (root == z_id) {
  905. root = y_id;
  906. }
  907. else if (root_id == z_id) {
  908. root_id = y_id;
  909. }
  910. // update a next reference to z_id (if any)
  911. if (mNode != NIL && Next(mNode) == z_id) {
  912. SetNext(mNode, y_id);
  913. }
  914. }
  915. FreeNode (z_id);
  916. unchecked{_version++;}
  917. return z_id;
  918. }
  919. /*
  920. * RBDeleteFixup()
  921. * Fix the specified tree for RedBlack properties
  922. *
  923. * returns: The id of the root
  924. */
  925. private int RBDeleteFixup (int root_id, int x_id, int px_id /* px is parent of x */, int mainTreeNodeID)
  926. { //x is successor's non nil child or nil if both children are nil
  927. int w_id;
  928. #if VerifyPath
  929. // by knowing the NodePath, when z_id is in a satellite branch we don't have to Search for mainTreeNodeID
  930. (new NodePath(root_id, mainTreeNodeID)).VerifyPath(this);
  931. #endif
  932. if (x_id == NIL && px_id == NIL) {
  933. return NIL; //case of satelite tree root being deleted.
  934. }
  935. while (((root_id == NIL ? root : root_id) != x_id) && color (x_id) == NodeColor.black)
  936. {
  937. // (1) x's parent should have aleast 1 non-NIL child.
  938. // (2) check if x is a NIL left child or a non NIL left child
  939. if ((x_id != NIL && x_id == Left (Parent (x_id))) || (x_id == NIL && Left (px_id) == NIL))
  940. {
  941. // we have from DELETE, then x cannot be NIL and be a right child of its parent
  942. // also from DELETE, if x is non nil, it will be a left child.
  943. w_id = (x_id == NIL) ? Right (px_id) : Right (Parent (x_id)); // w is x's right sibling and it cannot be NIL
  944. if (w_id == NIL) {
  945. throw ExceptionBuilder.InternalRBTreeError(RBTreeError.RBDeleteFixup);
  946. }
  947. if (color (w_id) == NodeColor.red)
  948. {
  949. SetColor (w_id, NodeColor.black);
  950. SetColor (px_id, NodeColor.red);
  951. root_id = LeftRotate (root_id, px_id, mainTreeNodeID);
  952. w_id = (x_id == NIL) ? Right (px_id) : Right (Parent (x_id));
  953. }
  954. if (color (Left (w_id)) == NodeColor.black && color (Right (w_id)) == NodeColor.black)
  955. {
  956. SetColor (w_id, NodeColor.red);
  957. x_id = px_id;
  958. px_id = Parent (px_id); //maintain px_id
  959. }
  960. else
  961. {
  962. if (color (Right (w_id)) == NodeColor.black)
  963. {
  964. SetColor (Left (w_id), NodeColor.black);
  965. SetColor (w_id, NodeColor.red);
  966. root_id = RightRotate (root_id, w_id, mainTreeNodeID);
  967. w_id = (x_id == NIL) ? Right (px_id) : Right (Parent (x_id));
  968. }
  969. SetColor (w_id, color (px_id));
  970. SetColor (px_id, NodeColor.black);
  971. SetColor (Right (w_id), NodeColor.black);
  972. root_id = LeftRotate (root_id, px_id, mainTreeNodeID);
  973. x_id = (root_id == NIL) ? root : root_id;
  974. px_id = Parent (x_id);
  975. }
  976. }
  977. else
  978. { //x is a right child or it is NIL
  979. w_id = Left (px_id);
  980. if (color (w_id) == NodeColor.red)
  981. { // x_id is y's (the spliced node) sole non-NIL child or NIL if y had no children
  982. SetColor (w_id, NodeColor.black);
  983. if (x_id != NIL) {
  984. SetColor (px_id, NodeColor.red);
  985. root_id = RightRotate (root_id, px_id, mainTreeNodeID);
  986. w_id = (x_id == NIL) ? Left (px_id) : Left (Parent (x_id));
  987. }
  988. else {
  989. //we have from DELETE, then x cannot be NIL and be a right child of its parent
  990. // w_id cannot be nil.
  991. SetColor (px_id, NodeColor.red);
  992. root_id = RightRotate (root_id, px_id, mainTreeNodeID);
  993. w_id = (x_id == NIL) ? Left (px_id) : Left (Parent (x_id));
  994. if (w_id == NIL) {
  995. throw ExceptionBuilder.InternalRBTreeError(RBTreeError.CannotRotateInvalidsuccessorNodeinDelete);
  996. }
  997. }
  998. }
  999. if (color (Right (w_id)) == NodeColor.black && color (Left (w_id)) == NodeColor.black) {
  1000. SetColor (w_id, NodeColor.red);
  1001. x_id = px_id;
  1002. px_id = Parent (px_id);
  1003. }
  1004. else {
  1005. if (color (Left (w_id)) == NodeColor.black)
  1006. {
  1007. SetColor (Right (w_id), NodeColor.black);
  1008. SetColor (w_id, NodeColor.red);
  1009. root_id = LeftRotate (root_id, w_id, mainTreeNodeID);
  1010. w_id = (x_id == NIL) ? Left (px_id) : Left (Parent (x_id));
  1011. }
  1012. if (x_id != NIL)
  1013. {
  1014. SetColor (w_id, color (px_id));
  1015. SetColor (px_id, NodeColor.black);
  1016. SetColor (Left (w_id), NodeColor.black);
  1017. root_id = RightRotate (root_id, px_id, mainTreeNodeID);
  1018. x_id = (root_id == NIL) ? root : root_id;
  1019. px_id = Parent (x_id);
  1020. }
  1021. else
  1022. {
  1023. SetColor (w_id, color (px_id));
  1024. SetColor (px_id, NodeColor.black);
  1025. SetColor (Left (w_id), NodeColor.black);
  1026. root_id = RightRotate (root_id, px_id, mainTreeNodeID);
  1027. x_id = (root_id == NIL) ? root : root_id;
  1028. px_id = Parent (x_id);
  1029. }
  1030. }
  1031. }
  1032. }
  1033. SetColor (x_id, NodeColor.black);
  1034. return root_id;
  1035. }
  1036. private int SearchSubTree (int root_id, K key)
  1037. {
  1038. if (root_id != NIL && _accessMethod!=TreeAccessMethod.KEY_SEARCH_AND_INDEX) {
  1039. throw ExceptionBuilder.InternalRBTreeError(RBTreeError.UnsupportedAccessMethodInNonNillRootSubtree);
  1040. }
  1041. int x_id = (root_id == NIL) ? root : root_id;
  1042. int c;
  1043. while (x_id != NIL)
  1044. {
  1045. c = (root_id == NIL) ? CompareNode (key, Key (x_id)) : CompareSateliteTreeNode (key, Key (x_id));
  1046. if (c == 0) {
  1047. break;
  1048. }
  1049. if (c < 0) {
  1050. #if VerifySort
  1051. Debug.Assert((NIL == Left(x_id)) || (0 > Compare(root_id, Left(x_id), x_id)), "Search duplicate Left is not left");
  1052. #endif
  1053. x_id = Left (x_id);
  1054. }
  1055. else {
  1056. #if VerifySort
  1057. Debug.Assert((NIL == Right(x_id)) || (0 < Compare(root_id, Right(x_id), x_id)), "Search duplicate Right is not right");
  1058. #endif
  1059. x_id = Right (x_id);
  1060. }
  1061. }
  1062. return x_id;
  1063. }
  1064. // only works on the main tree - does not work with satelite tree
  1065. public int Search (K key)
  1066. { // for performance reasons, written as a while loop instead of a recursive method
  1067. int x_id = root;
  1068. int c;
  1069. while (x_id != NIL)
  1070. {
  1071. c = CompareNode (key, Key (x_id));
  1072. if (c == 0) {
  1073. break;
  1074. }
  1075. if (c < 0) {
  1076. #if VerifySort
  1077. Debug.Assert((NIL == Left(x_id)) || (0 > Compare(NIL, Left(x_id), x_id)), "Search Left is not left");
  1078. #endif
  1079. x_id = Left (x_id);
  1080. }
  1081. else {
  1082. #if VerifySort
  1083. Debug.Assert((NIL == Right(x_id)) || (0 < Compare(NIL, Right(x_id), x_id)), "Search Right is not right");
  1084. #endif
  1085. x_id = Right (x_id);
  1086. }
  1087. }
  1088. return x_id;
  1089. }
  1090. // To simulate direct access for records[index]= record
  1091. /// <summary>
  1092. /// return key associated with the specified value. Specifically, return record for specified index/value
  1093. /// indexer
  1094. /// </summary>
  1095. /// <exception cref="IndexOutOfRangeException"></exception>
  1096. // return record i.e key at specified index
  1097. public K this[int index]
  1098. {
  1099. get
  1100. {
  1101. return Key(GetNodeByIndex(index).NodeID);
  1102. }
  1103. }
  1104. // Get Record(s) having same key value as that of specified record. Then scan the matched nodes
  1105. // and return the node with the matching record
  1106. /// <returns>Determine node and the branch it took to get there.</returns>
  1107. private NodePath GetNodeByKey(K key) //i.e. GetNodeByKey
  1108. {
  1109. int nodeId = SearchSubTree(NIL, key);
  1110. if (Next (nodeId) != NIL) {
  1111. return new NodePath(SearchSubTree(Next(nodeId), key), nodeId);
  1112. }
  1113. else if (!Key(nodeId).Equals(key)) {
  1114. nodeId = NIL;
  1115. }
  1116. return new NodePath(nodeId, NIL);
  1117. }
  1118. /*
  1119. * GetIndexByRecord()
  1120. * Gets index of the specified record. returns (-1) if specified record is not found.
  1121. */
  1122. public int GetIndexByKey (K key)
  1123. {
  1124. int nodeIndex = -1;
  1125. NodePath nodeId = GetNodeByKey (key);
  1126. if (nodeId.NodeID != NIL) {
  1127. nodeIndex = GetIndexByNodePath (nodeId);
  1128. }
  1129. return nodeIndex;
  1130. }
  1131. /*
  1132. * GetIndexByNode()
  1133. *
  1134. * If I am right child then size=my size + size of left child of my parent + 1
  1135. * go up till root, if right child keep adding to the size.
  1136. * (1) compute rank in main tree.
  1137. * (2) if node member of a satelite tree, add to rank its relative rank in that tree.
  1138. *
  1139. * Rank:
  1140. * Case 1: Node is in Main RBTree only
  1141. * Its rank/index is its main tree index
  1142. * Case 2: Node is in a Satelite tree only
  1143. * Its rank/index is its satelite tree index
  1144. * Case 3: Nodes is in both Main and Satelite RBTree (a main tree node can be a satelite tree root)
  1145. * Its rank/index is its main tree index + its satelite tree index - 1
  1146. * Returns the index of the specified node.
  1147. * returns -1, if the specified Node is tree.NIL.
  1148. *
  1149. * Assumption: The specified node always exist in the tree.
  1150. */
  1151. // SQLBU 428961: Serious performance issue when creating DataView
  1152. // this improves performance when used heavily, like with the default view (creating before rows added)
  1153. public int GetIndexByNode (int node)
  1154. {
  1155. Debug.Assert(NIL != node, "GetIndexByNode(NIL)");
  1156. if (0 == _inUseSatelliteTreeCount)
  1157. { // compute from the main tree when no satellite branches exist
  1158. return ComputeIndexByNode(node);
  1159. }
  1160. else if (NIL != Next(node))
  1161. { // node is a main tree node
  1162. #if VerifyIndex && VerifyPath
  1163. (new NodePath(Next(node), node)).VerifyPath(this);
  1164. #endif
  1165. return ComputeIndexWithSatelliteByNode(node);
  1166. }
  1167. else
  1168. {
  1169. int mainTreeNodeId = SearchSubTree(NIL, Key(node));
  1170. if (mainTreeNodeId == node)
  1171. { // node is a main tree node
  1172. #if VerifyIndex && VerifyPath
  1173. (new NodePath(node, NIL)).VerifyPath(this);
  1174. #endif
  1175. return ComputeIndexWithSatelliteByNode(node);
  1176. }
  1177. else
  1178. { //compute the main tree rank + satellite branch rank
  1179. #if VerifyIndex && VerifyPath
  1180. (new NodePath(node, mainTreeNodeId)).VerifyPath(this);
  1181. #endif
  1182. return ComputeIndexWithSatelliteByNode(mainTreeNodeId) +
  1183. ComputeIndexByNode(node);
  1184. }
  1185. }
  1186. }
  1187. /// <summary>Determine tree index position from node path.</summary>
  1188. /// <remarks>This differs from GetIndexByNode which would search for the main tree node instead of just knowing it</remarks>
  1189. private int GetIndexByNodePath(NodePath path)
  1190. {
  1191. #if VerifyIndex && VerifyPath
  1192. path.VerifyPath(this);
  1193. #endif
  1194. if (0 == _inUseSatelliteTreeCount)
  1195. { // compute from the main tree when no satellite branches exist
  1196. return ComputeIndexByNode(path.NodeID);
  1197. }
  1198. else if (NIL == path.MainTreeNodeID)
  1199. { // compute from the main tree accounting for satellite branches
  1200. return ComputeIndexWithSatelliteByNode(path.NodeID);
  1201. }
  1202. else
  1203. { //compute the main tree rank + satellite branch rank
  1204. return ComputeIndexWithSatelliteByNode(path.MainTreeNodeID) +
  1205. ComputeIndexByNode(path.NodeID);
  1206. }
  1207. }
  1208. private int ComputeIndexByNode(int nodeId) {
  1209. #if VerifyIndex
  1210. Debug.Assert(NIL != nodeId, "ComputeIndexByNode(NIL)");
  1211. #endif
  1212. int myRank = SubTreeSize(Left(nodeId));
  1213. while (nodeId != NIL)
  1214. {
  1215. #if VerifyIndex && VerifyPath
  1216. Debug.Assert(NIL == Next(nodeId), "Next not NIL");
  1217. #endif
  1218. int parent = Parent(nodeId);
  1219. if (nodeId == Right(parent))
  1220. {
  1221. myRank += (SubTreeSize(Left(parent)) + 1);
  1222. }
  1223. nodeId = parent;
  1224. }
  1225. return myRank;
  1226. }
  1227. private int ComputeIndexWithSatelliteByNode(int nodeId) {
  1228. #if VerifyIndex
  1229. Debug.Assert(NIL != nodeId, "ComputeIndexWithSatelliteByNode(NIL)");
  1230. #endif
  1231. int myRank = SubTreeSize(Left(nodeId));
  1232. while (nodeId != NIL)
  1233. {
  1234. int parent = Parent(nodeId);
  1235. if (nodeId == Right(parent))
  1236. {
  1237. myRank += (SubTreeSize(Left(parent)) + ((Next(parent) == NIL) ? 1 : SubTreeSize(Next(parent))));
  1238. }
  1239. nodeId = parent;
  1240. }
  1241. return myRank;
  1242. }
  1243. /// <returns>Determine node and the branch it took to get there.</returns>
  1244. /// <exception cref="IndexOutOfRangeException"></exception>
  1245. private NodePath GetNodeByIndex(int userIndex)
  1246. {
  1247. int x_id, satelliteRootId;
  1248. if (0 == _inUseSatelliteTreeCount) {
  1249. // if rows were only contigously append, then using (userIndex -= _pageTable[i].InUseCount) would
  1250. // be faster for the first 12 pages (about 5248) nodes before (log2 of Count) becomes faster again.
  1251. // the additional complexity was deemed not worthy for the possible perf gain
  1252. // computation cost is (log2 of Count)
  1253. x_id = ComputeNodeByIndex(root, unchecked(userIndex + 1));
  1254. satelliteRootId = NIL;
  1255. }
  1256. else {
  1257. // computation cost is ((log2 of Distinct Count) + (log2 of Duplicate Count))
  1258. x_id = ComputeNodeByIndex(userIndex, out satelliteRootId);
  1259. }
  1260. if (x_id == NIL) {
  1261. if (TreeAccessMethod.INDEX_ONLY == _accessMethod) {
  1262. throw ExceptionBuilder.RowOutOfRange(userIndex);
  1263. }
  1264. else {
  1265. throw ExceptionBuilder.InternalRBTreeError(RBTreeError.IndexOutOFRangeinGetNodeByIndex);
  1266. }
  1267. }
  1268. return new NodePath(x_id, satelliteRootId);
  1269. }
  1270. private int ComputeNodeByIndex(int index, out int satelliteRootId)
  1271. {
  1272. index = unchecked(index + 1); // index is 0 based, while size is 1 based.
  1273. satelliteRootId = NIL;
  1274. int x_id = root;
  1275. int rank = -1;
  1276. while (x_id != NIL && !(((rank = SubTreeSize (Left (x_id)) + 1) == index) && Next (x_id) == NIL))
  1277. {
  1278. if (index < rank) {
  1279. x_id = Left (x_id);
  1280. }
  1281. else if (Next (x_id) != NIL && index >= rank && index <= rank + SubTreeSize (Next (x_id)) - 1)
  1282. {
  1283. // node with matching index is in the associated satellite tree. continue searching for index in satellite tree.
  1284. satelliteRootId = x_id;
  1285. index = index - rank + 1; // rank is SubTreeSize(Node.left)+1, we do +1 here to offset +1 done in rank. index -= rank;
  1286. return ComputeNodeByIndex(Next(x_id), index); //satellite tree root
  1287. }
  1288. else
  1289. {
  1290. if (Next (x_id) == NIL)
  1291. index -= rank;
  1292. else
  1293. index -= rank + SubTreeSize (Next (x_id)) - 1;
  1294. x_id = Right (x_id);
  1295. }
  1296. }
  1297. return x_id;
  1298. }
  1299. private int ComputeNodeByIndex(int x_id, int index) {
  1300. while (x_id != NIL) {
  1301. Debug.Assert(NIL == Next(x_id), "has unexpected satellite tree");
  1302. int y_id = Left(x_id);
  1303. int rank = SubTreeSize(y_id) + 1;
  1304. if (index < rank) {
  1305. x_id = y_id;
  1306. }
  1307. else if (rank < index) {
  1308. x_id = Right(x_id);
  1309. index -= rank;
  1310. }
  1311. else {
  1312. break;
  1313. }
  1314. }
  1315. return x_id;
  1316. }
  1317. #if DEBUG
  1318. // return true if all nodes are unique; i.e. no satelite trees.
  1319. public bool CheckUnique (int curNodeId)
  1320. {
  1321. if (curNodeId != NIL)
  1322. {
  1323. if (Next (curNodeId) != NIL)
  1324. return false; // atleast 1 duplicate found
  1325. if (!CheckUnique (Left (curNodeId)) || !CheckUnique (Right (curNodeId)))
  1326. return false;
  1327. }
  1328. return true;
  1329. }
  1330. #endif
  1331. public int Insert (K item)
  1332. {
  1333. int nodeId = GetNewNode(item);
  1334. RBInsert (NIL, nodeId, NIL, -1, false);
  1335. return nodeId;
  1336. }
  1337. // Begin: List of methods for making it easy to work with ArrayList
  1338. public int Add(K item) //Insert (int record)
  1339. {
  1340. int nodeId = GetNewNode (item);
  1341. RBInsert(NIL, nodeId, NIL, -1, false);
  1342. return nodeId;
  1343. }
  1344. public IEnumerator GetEnumerator() {
  1345. return new RBTreeEnumerator(this);
  1346. }
  1347. // *****BruteForceImplementation*****
  1348. //
  1349. // iterate over all nodes, InOrder and return index of node with the specified Item
  1350. // For the short term use a recursive method, later re-write it based on a stack data structure (if needed)
  1351. public int IndexOf (int nodeId, K item)
  1352. {
  1353. int index = -1;
  1354. // BIG ASSUMPTION: There is not satellite tree, this is INDEX_ONLY.
  1355. if (nodeId != NIL)
  1356. {
  1357. if ( (Object) Key(nodeId) == (Object)item) {
  1358. return GetIndexByNode(nodeId);
  1359. }
  1360. if ( (index=IndexOf(Left(nodeId), item)) != -1) {
  1361. return index;
  1362. }
  1363. if ( (index=IndexOf(Right(nodeId), item)) != -1) {
  1364. return index;
  1365. }
  1366. }
  1367. return index;
  1368. }
  1369. public int Insert(int position, K item) //Insert (int record)
  1370. {
  1371. return InsertAt(position, item, false);
  1372. }
  1373. public int InsertAt(int position, K item, bool append)
  1374. {
  1375. int nodeId = GetNewNode (item);
  1376. RBInsert (NIL, nodeId, NIL, position, append);
  1377. return nodeId;
  1378. }
  1379. public void RemoveAt(int position)
  1380. {
  1381. DeleteByIndex(position);
  1382. }
  1383. public void Clear()
  1384. {
  1385. InitTree();
  1386. unchecked{_version++;}
  1387. }
  1388. public void CopyTo(Array array, int index) {
  1389. if (array==null) {
  1390. throw ExceptionBuilder.ArgumentNull("array");
  1391. }
  1392. if (index < 0) {
  1393. throw ExceptionBuilder.ArgumentOutOfRange("index");
  1394. }
  1395. int count = Count;
  1396. if (array.Length - index < Count) {
  1397. throw ExceptionBuilder.InvalidOffsetLength();
  1398. }
  1399. int x_id = Minimum(root);
  1400. for(int i = 0; i < count; ++i) {
  1401. array.SetValue(Key(x_id), index + i);
  1402. x_id = Successor(x_id);
  1403. }
  1404. }
  1405. public void CopyTo(K[] array, int index) {
  1406. if (array==null) {
  1407. throw ExceptionBuilder.ArgumentNull("array");
  1408. }
  1409. if (index < 0) {
  1410. throw ExceptionBuilder.ArgumentOutOfRange("index");
  1411. }
  1412. int count = Count;
  1413. if (array.Length - index < Count) {
  1414. throw ExceptionBuilder.InvalidOffsetLength();
  1415. }
  1416. int x_id = Minimum(root);
  1417. for(int i = 0; i < count; ++i) {
  1418. array[index + i] = Key(x_id);
  1419. x_id = Successor(x_id);
  1420. }
  1421. }
  1422. // End: List of methods for making it easy to work with ArrayList
  1423. private void SetRight (int nodeId, int rightNodeId)
  1424. {
  1425. /*
  1426. TreePage page = _pageTable[nodeId >> 16];
  1427. int slotIndex = nodeId & 0xFFFF;
  1428. page.Slots[slotIndex].rightId = rightNodeId;
  1429. */
  1430. _pageTable[nodeId >> 16].Slots[nodeId & 0xFFFF].rightId = rightNodeId;
  1431. }
  1432. private void SetLeft (int nodeId, int leftNodeId)
  1433. {
  1434. /*
  1435. TreePage page = _pageTable[nodeId >> 16];
  1436. int slotIndex = nodeId & 0xFFFF;
  1437. page.Slots[slotIndex].leftId = leftNodeId;
  1438. */
  1439. _pageTable[nodeId >> 16].Slots[nodeId & 0xFFFF].leftId = leftNodeId;
  1440. }
  1441. private void SetParent (int nodeId, int parentNodeId)
  1442. {
  1443. Debug.Assert(nodeId != NIL, " in SetParent nodeId == NIL");
  1444. /*
  1445. TreePage page = _pageTable[nodeId >> 16];
  1446. int slotIndex = nodeId & 0xFFFF;
  1447. page.Slots[slotIndex].parentId = parentNodeId;
  1448. */
  1449. _pageTable[nodeId >> 16].Slots[nodeId & 0xFFFF].parentId = parentNodeId;
  1450. }
  1451. private void SetColor (int nodeId, NodeColor color)
  1452. {
  1453. Debug.Assert(nodeId != NIL, " in SetColor nodeId == NIL");
  1454. /*
  1455. TreePage page = _pageTable[nodeId >> 16];
  1456. int slotIndex = nodeId & 0xFFFF;
  1457. page.Slots[slotIndex].nodeColor = color;
  1458. */
  1459. _pageTable[nodeId >> 16].Slots[nodeId & 0xFFFF].nodeColor = color;
  1460. }
  1461. private void SetKey (int nodeId, K key)
  1462. {
  1463. /*
  1464. TreePage page = _pageTable[nodeId >> 16];
  1465. int slotIndex = nodeId & 0xFFFF;
  1466. page.Slots[slotIndex].keyOfNode = key;
  1467. */
  1468. _pageTable[nodeId >> 16].Slots[nodeId & 0xFFFF].keyOfNode = key;
  1469. }
  1470. private void SetNext (int nodeId, int nextNodeId)
  1471. {
  1472. /*
  1473. TreePage page = _pageTable[nodeId >> 16];
  1474. int slotIndex = nodeId & 0xFFFF;
  1475. page.Slots[slotIndex].nextId = nextNodeId;
  1476. */
  1477. _pageTable[nodeId >> 16].Slots[nodeId & 0xFFFF].nextId = nextNodeId;
  1478. }
  1479. private void SetSubTreeSize (int nodeId, int size)
  1480. {
  1481. Debug.Assert(nodeId != NIL &&
  1482. (size != 0 || _pageTable[nodeId >> 16].Slots[nodeId & 0xFFFF].selfId == NIL) &&
  1483. (size != 1 || _pageTable[nodeId >> 16].Slots[nodeId & 0xFFFF].nextId == NIL), "SetSize");
  1484. // SQLBU 428961: Serious performance issue when creating DataView
  1485. // this improves performance by reducing the impact of this heavily used method
  1486. _pageTable[nodeId >> 16].Slots[nodeId & 0xFFFF].subTreeSize = size;
  1487. VerifySize(nodeId, size);
  1488. }
  1489. private void IncreaseSize (int nodeId)
  1490. {
  1491. /*
  1492. TreePage page = _pageTable[nodeId >> 16];
  1493. int slotIndex = nodeId & 0xFFFF;
  1494. page.Slots[slotIndex].subTreeSize += 1;
  1495. */
  1496. _pageTable[nodeId >> 16].Slots[nodeId & 0xFFFF].subTreeSize += 1;
  1497. }
  1498. private void RecomputeSize(int nodeId)
  1499. {
  1500. int myCorrectSize = SubTreeSize (Left (nodeId)) + SubTreeSize (Right (nodeId)) + (Next (nodeId) == NIL ? 1 : SubTreeSize (Next (nodeId)));
  1501. /*
  1502. TreePage page = _pageTable[nodeId >> 16];
  1503. int slotIndex = nodeId & 0xFFFF;
  1504. page.Slots[slotIndex].subTreeSize = myCorrectSize;
  1505. */
  1506. _pageTable[nodeId >> 16].Slots[nodeId & 0xFFFF].subTreeSize = myCorrectSize;
  1507. }
  1508. private void DecreaseSize (int nodeId)
  1509. {
  1510. /*
  1511. TreePage page = _pageTable[nodeId >> 16];
  1512. int slotIndex = nodeId & 0xFFFF;
  1513. page.Slots[slotIndex].subTreeSize -= 1;
  1514. */
  1515. _pageTable[nodeId >> 16].Slots[nodeId & 0xFFFF].subTreeSize -= 1;
  1516. VerifySize(nodeId, _pageTable[nodeId >> 16].Slots[nodeId & 0xFFFF].subTreeSize);
  1517. }
  1518. [ConditionalAttribute("DEBUG")]
  1519. private void VerifySize(int nodeId, int size) {
  1520. int myCorrectSize = SubTreeSize(Left(nodeId)) + SubTreeSize(Right(nodeId)) + (Next(nodeId) == NIL ? 1 : SubTreeSize(Next(nodeId)));
  1521. Debug.Assert(myCorrectSize == size, "VerifySize");
  1522. }
  1523. public int Right (int nodeId)
  1524. {
  1525. /*
  1526. TreePage page = _pageTable[nodeId >> 16];
  1527. int slotIndex = nodeId & 0xFFFF;
  1528. int rightId = page.Slots[slotIndex].rightId;
  1529. return rightId;
  1530. */
  1531. return (_pageTable[nodeId >> 16].Slots[nodeId & 0xFFFF].rightId);
  1532. }
  1533. public int Left (int nodeId)
  1534. {
  1535. /*
  1536. TreePage page = _pageTable[nodeId >> 16];
  1537. int slotIndex = nodeId & 0xFFFF;
  1538. int leftId = page.Slots[slotIndex].leftId;
  1539. return leftId;
  1540. */
  1541. return (_pageTable[nodeId >> 16].Slots[nodeId & 0xFFFF].leftId);
  1542. }
  1543. public int Parent (int nodeId)
  1544. {
  1545. /*
  1546. TreePage page = _pageTable[nodeId >> 16];
  1547. int slotIndex = nodeId & 0xFFFF;
  1548. int parentId = page.Slots[slotIndex].parentId;
  1549. return parentId;
  1550. */
  1551. return (_pageTable[nodeId >> 16].Slots[nodeId & 0xFFFF].parentId);
  1552. }
  1553. private NodeColor color (int nodeId)
  1554. {
  1555. /*
  1556. TreePage page = _pageTable[nodeId >> 16];
  1557. int slotIndex = nodeId & 0xFFFF;
  1558. NodeColor col = page.Slots[slotIndex].nodeColor;
  1559. return col;
  1560. */
  1561. return (_pageTable[nodeId >> 16].Slots[nodeId & 0xFFFF].nodeColor);
  1562. }
  1563. public int Next (int nodeId)
  1564. {
  1565. /*
  1566. TreePage page = _pageTable[nodeId >> 16];
  1567. int slotIndex = nodeId & 0xFFFF;
  1568. int nextId = page.Slots[slotIndex].nextId;
  1569. return nextId;
  1570. */
  1571. return (_pageTable[nodeId >> 16].Slots[nodeId & 0xFFFF].nextId);
  1572. }
  1573. public int SubTreeSize (int nodeId)
  1574. {
  1575. /*
  1576. TreePage page = _pageTable[nodeId >> 16];
  1577. int slotIndex = nodeId & 0xFFFF;
  1578. int size = page.Slots[slotIndex].subTreeSize;
  1579. return size;
  1580. */
  1581. return (_pageTable[nodeId >> 16].Slots[nodeId & 0xFFFF].subTreeSize);
  1582. }
  1583. public K Key (int nodeId)
  1584. {
  1585. /*
  1586. TreePage page = _pageTable[nodeId >> 16];
  1587. int slotIndex = nodeId & 0xFFFF;
  1588. K key = page.Slots[slotIndex].keyOfNode;
  1589. return key;
  1590. */
  1591. return (_pageTable[nodeId >> 16].Slots[nodeId & 0xFFFF].keyOfNode);
  1592. }
  1593. private enum NodeColor {
  1594. red = 0,
  1595. black = 1,
  1596. };
  1597. private struct Node
  1598. {
  1599. internal int selfId;
  1600. internal int leftId;
  1601. internal int rightId;
  1602. internal int parentId;
  1603. internal int nextId; // multiple records associated with same key
  1604. internal int subTreeSize; // number of nodes in subtree rooted at the current node
  1605. internal K keyOfNode;
  1606. internal NodeColor nodeColor;
  1607. }
  1608. /// <summary>Represents the node in the tree and the satellite branch it took to get there.</summary>
  1609. private struct NodePath
  1610. {
  1611. /// <summary>Represents the node in the tree</summary>
  1612. internal readonly int NodeID;
  1613. /// <summary>
  1614. /// When not NIL, it represents the fact NodeID is has duplicate values in the tree.
  1615. /// This is the 'fake' node in the main tree that redirects to the root of the satellite tree.
  1616. /// By tracking this value, we don't have to repeatedly search for this node.
  1617. /// </summary>
  1618. internal readonly int MainTreeNodeID;
  1619. internal NodePath(int nodeID, int mainTreeNodeID)
  1620. {
  1621. NodeID = nodeID;
  1622. MainTreeNodeID = mainTreeNodeID;
  1623. }
  1624. #if VerifyPath
  1625. internal void VerifyPath(RBTree<K> tree)
  1626. {
  1627. Debug.Assert(null != tree, "null tree");
  1628. Debug.Assert((NIL == NodeID && NIL == MainTreeNodeID) || (NIL != NodeID), "MainTreeNodeID is not NIL");
  1629. if (NIL != MainTreeNodeID)
  1630. {
  1631. Debug.Assert(NIL != tree.Next(MainTreeNodeID), "MainTreeNodeID should have a Next");
  1632. int node = MainTreeNodeID;
  1633. while (NIL != tree.Parent(node))
  1634. {
  1635. node = tree.Parent(node);
  1636. }
  1637. Debug.Assert(tree.root == node, "MainTreeNodeID parent change doesn't align");
  1638. }
  1639. if (NIL != NodeID)
  1640. {
  1641. Debug.Assert(NIL == tree.Next(NodeID), "NodeID should not have a Next");
  1642. int node = NodeID;
  1643. if (NIL == MainTreeNodeID) {
  1644. while (NIL != tree.Parent(node))
  1645. {
  1646. node = tree.Parent(node);
  1647. }
  1648. }
  1649. else {
  1650. while (NIL != tree.Parent(node))
  1651. {
  1652. Debug.Assert(NIL == tree.Next(node), "duplicate node should not have a next");
  1653. node = tree.Parent(node);
  1654. }
  1655. }
  1656. Debug.Assert((NIL == MainTreeNodeID && tree.root == node) ||
  1657. (tree.Next(MainTreeNodeID) == node), "NodeID parent change doesn't align");
  1658. }
  1659. }
  1660. #endif
  1661. }
  1662. private sealed class TreePage {
  1663. public const Int32 slotLineSize = 32;
  1664. internal readonly Node[] Slots; // List of slots
  1665. internal readonly Int32[] SlotMap; // CEILING(slots.size/slotLineSize)
  1666. private Int32 _inUseCount; // 0 to _slots.size
  1667. private Int32 _pageId; // Page's Id
  1668. private Int32 _nextFreeSlotLine; // o based position of next free slot line
  1669. /*
  1670. * size: number of slots per page. Maximum allowed is 64K
  1671. */
  1672. internal TreePage (int size)
  1673. {
  1674. if (size > 64 * 1024) {
  1675. throw ExceptionBuilder.InternalRBTreeError(RBTreeError.InvalidPageSize);
  1676. }
  1677. Slots = new Node[size];
  1678. SlotMap = new Int32[(size + slotLineSize - 1) / slotLineSize];
  1679. }
  1680. /*
  1681. * Allocate a free slot from the current page belonging to the specified tree.
  1682. * return the Id of the allocated slot, or -1 if the current page does not have any free slots.
  1683. */
  1684. internal int AllocSlot (RBTree<K> tree)
  1685. {
  1686. int segmentPos = 0; // index into _SlotMap
  1687. Int32 freeSlot = 0; // Uint, slot offset within the segment
  1688. int freeSlotId = -1; // 0 based slot position
  1689. if (_inUseCount < Slots.Length)
  1690. {
  1691. segmentPos = _nextFreeSlotLine;
  1692. while (segmentPos < SlotMap.Length)
  1693. {
  1694. if (((UInt32)SlotMap[segmentPos]) < 0xFFFFFFFF)
  1695. {
  1696. freeSlotId = 0;
  1697. freeSlot = (~(SlotMap[segmentPos])) & (SlotMap[segmentPos] + 1);
  1698. // avoid string concat to allow debug code to run faster
  1699. Debug.Assert((SlotMap[segmentPos] & freeSlot) == 0,"Slot position segment[segmentPos ]: [freeSlot] is in use. Expected to be empty");
  1700. SlotMap[segmentPos] |= freeSlot; //mark free slot as used.
  1701. _inUseCount++;
  1702. if (_inUseCount == Slots.Length) // mark page as full
  1703. tree.MarkPageFull (this);
  1704. tree._inUseNodeCount++;
  1705. // convert freeSlotPos to int value giving number of 0's to its right i.e. freeSlotId
  1706. freeSlotId = GetIntValueFromBitMap((uint)freeSlot);
  1707. _nextFreeSlotLine = segmentPos;
  1708. freeSlotId = (segmentPos * TreePage.slotLineSize) + freeSlotId;
  1709. break;
  1710. }
  1711. else
  1712. {
  1713. segmentPos++;
  1714. }
  1715. }
  1716. if (freeSlotId == -1 && _nextFreeSlotLine != 0)
  1717. {
  1718. //Try one more time, starting from 0th segment position to locate a free slot.
  1719. _nextFreeSlotLine = 0;
  1720. freeSlotId = AllocSlot (tree);
  1721. }
  1722. }
  1723. return freeSlotId; // 0 based slot position
  1724. }
  1725. internal Int32 InUseCount
  1726. {
  1727. get {return _inUseCount;}
  1728. set {_inUseCount = value;}
  1729. }
  1730. internal Int32 PageId
  1731. {
  1732. get { return _pageId; }
  1733. set { _pageId = value; }
  1734. }
  1735. }
  1736. // SQLBU 428961: Serious performance issue when creating DataView
  1737. // this improves performance allowing to iterating of the index instead of computing record by index
  1738. // changes are required to handle satellite nodes which do not exist in DataRowCollection
  1739. // enumerator over index will not be handed to the user, only used internally
  1740. // instance of this enumerator will be handed to the user via DataRowCollection.GetEnumerator()
  1741. internal struct RBTreeEnumerator : System.Collections.Generic.IEnumerator<K>, System.Collections.IEnumerator
  1742. {
  1743. private readonly RBTree<K> tree;
  1744. private readonly int version;
  1745. private int index, mainTreeNodeId;
  1746. private K current;
  1747. internal RBTreeEnumerator(RBTree<K> tree) {
  1748. this.tree = tree;
  1749. version = tree._version;
  1750. index = NIL;
  1751. mainTreeNodeId = tree.root;
  1752. current = default(K);
  1753. }
  1754. internal RBTreeEnumerator(RBTree<K> tree, int position)
  1755. {
  1756. this.tree = tree;
  1757. version = tree._version;
  1758. if (0 == position)
  1759. {
  1760. index = NIL;
  1761. mainTreeNodeId = tree.root;
  1762. }
  1763. else
  1764. {
  1765. index = tree.ComputeNodeByIndex(position-1, out mainTreeNodeId);
  1766. if (NIL == index)
  1767. {
  1768. throw ExceptionBuilder.InternalRBTreeError(RBTreeError.IndexOutOFRangeinGetNodeByIndex);
  1769. }
  1770. }
  1771. current = default(K);
  1772. }
  1773. public void Dispose() {
  1774. }
  1775. public bool MoveNext() {
  1776. if (version != tree._version) {
  1777. throw ExceptionBuilder.EnumeratorModified();
  1778. }
  1779. bool hasCurrent = tree.Successor(ref index, ref mainTreeNodeId);
  1780. current = tree.Key(index);
  1781. return hasCurrent;
  1782. }
  1783. public K Current {
  1784. get {
  1785. return current;
  1786. }
  1787. }
  1788. Object System.Collections.IEnumerator.Current {
  1789. get {
  1790. return Current;
  1791. }
  1792. }
  1793. void System.Collections.IEnumerator.Reset() {
  1794. if (version != tree._version) {
  1795. throw ExceptionBuilder.EnumeratorModified();
  1796. }
  1797. index = NIL;
  1798. mainTreeNodeId = tree.root;
  1799. current = default(K);
  1800. }
  1801. }
  1802. }
  1803. }