예제 #1
0
파일: BTree.cs 프로젝트: luanzhu/OOD.NET
		public BTree(uint topSid, SegmentManager sm, IKey keyFactory)
		{
			this.m_top_sid = topSid;
			this.m_sgManager = sm;
			this.m_keyFactory = keyFactory;
			this.m_nodeFactory = new BNode();
		}
예제 #2
0
		/// <summary>
		/// Create the internal storage for the dbFile.
		/// Note:
		///   1. a helper file for segment managment b-tree is also created if this database file
		///      does not exist.
		/// </summary>
		/// <param name="dbFile"></param>
		public ObjectStore(string dbFileName)
		{
			m_dbFile = new DiskFile(dbFileName);
			m_indexFile = new DiskFile(dbFileName+".idx");
			m_indexPageManager = new memSegmentManager(m_indexFile);

			if (m_indexPageManager.Header.InitializeNeeded)
			{
				m_indexPageManager.Header.NextSegmentId = 0;
				m_indexPageManager.Header.NextObjectId = 0;
				m_indexPageManager.Header.NextClassId = 0;

				//initialize the segment b-tree's top node id
				OOD.Imp.Storage.BNode segTreeTop = new OOD.Imp.Storage.BNode();
				m_indexPageManager.GetNewSegment(segTreeTop);
				segTreeTop.SetOrder(m_segTreeNodeOrder);
				segTreeTop.Leaf = true;
				m_indexPageManager.Header.SegmentTreeTopNodeSId = segTreeTop.SegmentID;

				//initialize the space b-tree's top node id
				BNode spaceTreeTop = new BNode();
				m_indexPageManager.GetNewSegment(spaceTreeTop);
				spaceTreeTop.SetOrder(m_spaceTreeNodeOrder);
				spaceTreeTop.Leaf = true;
				m_indexPageManager.Header.FreeSpaceTreeTopNodeSId = spaceTreeTop.SegmentID;
			}

			m_segmentIndexTree = new SegTree(m_indexPageManager.Header.SegmentTreeTopNodeSId, m_indexPageManager);
			m_spaceIndexTree = new SpaceTree(m_indexPageManager.Header.FreeSpaceTreeTopNodeSId, m_indexPageManager, m_dbFile);

			m_dbSegmentManager = new dbSegmentManager(
				m_indexPageManager.Header.NextSegmentId,
				m_segmentIndexTree,
				m_spaceIndexTree,
				m_dbFile);


			if (m_indexPageManager.Header.InitializeNeeded)
			{
				BNode catalogTop = new BNode();
				m_dbSegmentManager.GetNewSegment(catalogTop);
				catalogTop.SetOrder(m_catalogTreeNodeOrder);
				catalogTop.Leaf = true;

				m_indexPageManager.Header.CatalogTreeTopNodeSId = catalogTop.SegmentID;
			}

			m_catalogTree = new CatalogTree(
				m_indexPageManager.Header.CatalogTreeTopNodeSId,
				m_dbSegmentManager,
				m_indexPageManager.Header.NextClassId);

			m_classCache = new LRUHashtable(m_cache_size, m_classCacheLimit);
			m_objectTreeCache = new LRUHashtable(m_cache_size, m_objectTreeCacheLimit);

			//bring top node's segment tree, space tree, catalog tree into cache, they will be needed anyway
			if (!m_indexPageManager.Header.InitializeNeeded)
			{
				m_indexPageManager.GetSegment(m_segmentIndexTree.TopNodSegId, new BNode(), new KSegId());
				m_indexPageManager.GetSegment(m_spaceIndexTree.TopNodeSId, new BNode(), new KOffset());
				m_dbSegmentManager.GetSegment(m_catalogTree.TopNodeSId, new BNode(), new KCatalog());
			}
		}
예제 #3
0
		/* operations regarding class information, scheme */
		public bool InsertClassIno(string className, string[] fieldNames, ref uint assignedCId, ref uint topNodeSId)
		{
			if (m_catalogTree.Search(className) != null)
				return false;
			//reserve a segment id for this class clustering's top node
			BNode classTopSid = new BNode();
			m_dbSegmentManager.GetNewSegment(classTopSid);
			classTopSid.SetOrder(m_classTreeNodeOrder);
			classTopSid.Leaf = true;
			topNodeSId = classTopSid.SegmentID;
			if (m_catalogTree.Insert(className, fieldNames, classTopSid.SegmentID, ref assignedCId) == false)
				throw new OOD.Exception.ProgramLogicError(
					this,
					"Inserting class information failed.");
			return true;
		}
예제 #4
0
파일: BTree.cs 프로젝트: luanzhu/OOD.NET
			public bool MoveNext() 
			{
				m_current_key_no ++;
				if (m_current_key_no < m_current_node.KeyNums)
				{
					m_current = m_current_node.GetKeyAt(m_current_key_no);
				}
				else
				{
					//this node is used up, try next one
					if (m_to_be_visited.Count >0)
					{
						m_current_node = (BNode)m_tree.m_sgManager.GetSegment(
							(uint)m_to_be_visited.Dequeue(),
							m_tree.m_nodeFactory,
							m_tree.m_keyFactory);
						Debug.Assert(m_current_node.KeyNums>0);
						if (!m_current_node.Leaf)
						{
							for (int i=0; i<=m_current_node.KeyNums; i++)
							{
								Debug.Assert(m_current_node.GetChildAt(i) >= 0);
								m_to_be_visited.Enqueue(m_current_node.GetChildAt(i));
							}
						}
						//locate the current to be the first one in the new node
						m_current_key_no = 0;
						m_current = m_current_node.GetKeyAt(0);
					}
					else
						m_current = null;
				}

				return m_current != null;
			}
예제 #5
0
파일: BTree.cs 프로젝트: luanzhu/OOD.NET
			public BTEnumerator(BTree tree) 
			{
				m_tree = tree;
				m_to_be_visited = new System.Collections.Queue();
				m_current = null;
				m_current_node = (BNode) m_tree.m_sgManager.GetSegment(m_tree.m_top_sid, m_tree.m_nodeFactory, m_tree.m_keyFactory);
				if (m_current_node.KeyNums >0)
				{
					for (int i=0; i<=m_current_node.KeyNums; i++)
					{
						m_to_be_visited.Enqueue(m_current_node.GetChildAt(i));
					}
				}
				m_current_key_no = -1;
			}
예제 #6
0
파일: BTree.cs 프로젝트: luanzhu/OOD.NET
		/// <summary>
		/// Given a key, search the node where the key is stored in the tree with root as the root node.
		/// </summary>
		/// <param name="root"></param>
		/// <param name="key"></param>
		/// <param name="pos">the location the key is stored in</param>
		/// <param name="visisted">all the visisted parent is saved in the stack.</param>
		/// <returns></returns>
		public BNode FindNode(BNode root, IKey key, ref int pos, System.Collections.Stack visited, System.Collections.Stack via)
		{
			Debug.Assert(visited != null);

			BNode n = root;
			pos = -1;
			IKey temp = null;
			while (!n.Leaf)
			{
				temp = n.SearchKey(key, ref pos);
				if (temp == null)
				{
					uint nextNodeId = n.GetChildAt(pos);
					visited.Push(n);
					via.Push(pos);
					
					n = (BNode)m_sgManager.GetSegment(nextNodeId, m_nodeFactory, m_keyFactory);
				}
				else
					return n;
			}

			//n is leaf
			temp = n.SearchKey(key, ref pos);
			if (temp == null)
				return null;
			else
				return n;
		}
예제 #7
0
파일: BTree.cs 프로젝트: luanzhu/OOD.NET
		/// <summary>
		/// Insert the newKey into this B-tree, 
		/// </summary>
		/// <param name="newKey"></param>
		/// <returns></returns>
		public bool Insert(IKey newKey)
		{
			//find the leaf where the newKey should be in
			BNode n = m_top;
			System.Collections.Stack visited = new System.Collections.Stack();
			int pos = -1;
			while (!n.Leaf)
			{
				IKey temp = n.SearchKey(newKey, ref pos);
				if (temp == null)
				{
					uint nextNodeId = n.GetChildAt(pos);
					visited.Push(n);
					
					n = (BNode)m_sgManager.GetSegment(nextNodeId, m_nodeFactory, m_keyFactory);
				}
				else
					return false;
			}
			
			//now BNode n is the leaf where insert should happen
			IKey t_temp = n.SearchKey(newKey, ref pos);
			if (t_temp == null)
			{
				//not exists, go ahead to insert the new key
				if (!n.IsFull)
				{
					n.InsertAtLeaf(newKey, pos);

					return true;
				}
				else
				{
					//split needed for this node
					BNode right = new BNode();
					m_sgManager.GetNewSegment(right);
					IKey median = null;
					n.SplitAtLeaf(newKey, pos,  ref median, ref right); //this split is at leaf

					bool finished = false;					
					//now n holds the left half of the items, 
					//right holds the right half items, median is the middle key

					while (!finished)
					{			
						//parent is node middle key will be inserted
						BNode parent = (visited.Count >0 ? (BNode)visited.Pop() : null);

						if (parent == null)
						{
							//new top node is needed
							BNode new_top = new BNode();
							m_sgManager.GetNewSegment(new_top);
							new_top.SetOrder(m_top.Order);
							new_top.Leaf = false;
							new_top.InsertFirstKey(median, n.SegmentID, right.SegmentID);

							this.m_top_sid = new_top.SegmentID;

							return true;
						}
						else
						{
							IKey tt = parent.SearchKey(median, ref pos);
							if (tt != null)
								return false;

							if (!parent.IsFull)
							{
								parent.InsertAtInternal(median, pos, right.SegmentID);
								return true;
							}
							else
							{
								//parent is full again
								BNode newRight = new BNode();
								m_sgManager.GetNewSegment(newRight);
								newRight.SetOrder(parent.Order);
								newRight.Leaf = parent.Leaf;
								//this split will insert median into the parent, then split and new middle key is newMedian
								IKey newMedian;
								parent.SplitAtInternal(median, pos, right.SegmentID, out newMedian, newRight);

								n = parent;
								median = newMedian;
								right = newRight;
							}

						}

					}


				}
			}
			else
				return false;

			return false;
		}
예제 #8
0
파일: BNode.cs 프로젝트: luanzhu/OOD.NET
		/// <summary>
		/// Distribute one key from left to right
		/// </summary>
		/// <param name="pos"></param>
		/// <param name="left"></param>
		/// <param name="right"></param>
		public void RedistributeLeft2Right(int pos, BNode left, BNode right)
		{
			Debug.Assert(pos >=0 && pos < m_keys.Length);
			Debug.Assert(m_children[pos] == left.SegmentID);
			Debug.Assert(m_children[pos+1] == right.SegmentID);
			Debug.Assert(m_keys[pos].CompareTo(left.m_keys[left.m_keyNums-1])>0);
			Debug.Assert(m_keys[pos].CompareTo(right.m_keys[right.m_keyNums-1])<0);

			Debug.Assert(right.KeyNums < m_order - 1);

			//shift everything in right for the new key
			for (int i=right.KeyNums; i>0; i--)
			{
				right.m_keys[i] = right.m_keys[i-1];
				right.m_children[i+1] = right.m_children[i]; 
			}
			right.m_children[1] = right.m_children[0];

			//copy middle key in parent to the first one of right
			right.m_keys[0] = m_keys[pos];
			right.m_children[0] = left.m_children[left.KeyNums]; //copy last pointer to be the first pointer in new right node
			right.m_keyNums++;

			//copy the last key in left into parent
			m_keys[pos] = left.m_keys[left.m_keyNums-1];

			//remove the last key from left
			left.m_keyNums--;

			this.m_dirty = true;
			left.m_dirty = true;
			right.m_dirty = true;
		}
예제 #9
0
파일: BNode.cs 프로젝트: luanzhu/OOD.NET
		/// <summary>
		/// Note:
		///  1. helper should be the realy key used in the b-tree.
		/// </summary>
		/// <param name="segmentId"></param>
		/// <param name="helper"></param>
		/// <param name="bytes"></param>
		/// <param name="offset"></param>
		/// <param name="count"></param>
		public override Segment Deserialize(uint segmentId, object helper, byte[] bytes, int offset, int count)
		{

			IKey keyFactory = (IKey)helper;
			int pos = offset;
			short order = OOD.Utility.Bytes.Unpack2(bytes, pos);

			BNode result = new BNode(segmentId, order);

			pos += 2;
			result.m_leaf = (bytes[pos++] == 1);
			result.m_keyNums = OOD.Utility.Bytes.Unpack2(bytes, pos);
			pos += 2;
			for (int i=0; i<result.m_keyNums; i++)
			{
				int length = OOD.Utility.Bytes.Unpack2(bytes, pos);
				pos += 2;
				result.m_keys[i] = keyFactory.Deserialize(bytes, pos, length);
				pos += length;
			}
			for (int i=0; i<=result.m_keyNums; i++)
			{
				result.m_children[i] = OOD.Utility.Bytes.Unpack4U(bytes, pos);
				pos += 4;
			}

			result.m_dirty = false;
			
			return result;
		}
예제 #10
0
파일: BNode.cs 프로젝트: luanzhu/OOD.NET
		/// <summary>
		/// Combine the left, right, along with the key in pos of this node into the new one, 
		/// and keep left, clear right one.
		/// </summary>
		/// <param name="pos">the location of the connecting key in this node(parent)</param>
		/// <param name="left"></param>
		/// <param name="right"></param>
		public void CombineChildren(int pos, BNode left, BNode right)
		{
			Debug.Assert(pos >=0 && pos < m_keys.Length);
			Debug.Assert(m_children[pos] == left.SegmentID);
			Debug.Assert(m_children[pos+1] == right.SegmentID);
			Debug.Assert(m_keys[pos].CompareTo(left.m_keys[left.m_keyNums-1])>0);
			Debug.Assert(m_keys[pos].CompareTo(right.m_keys[right.m_keyNums-1])<0);

			left.m_keys[left.m_keyNums] = m_keys[pos];
			left.m_children[left.m_keyNums+1] = right.m_children[0];
			left.m_keyNums ++ ;
			for (int i=0; i<right.m_keyNums; i++)
			{
				left.m_keys[left.m_keyNums++] = right.m_keys[i];
				left.m_children[left.m_keyNums] = right.m_children[i+1];
			}

			right.m_keyNums = 0;

			//remove pos record in the parent
			Remove(pos);

			this.m_dirty = true;
            left.m_dirty = true;
	        right.m_dirty = true;
		}
예제 #11
0
파일: BNode.cs 프로젝트: luanzhu/OOD.NET
		/// <summary>
		/// Redistribute one from right to left
		/// </summary>
		/// <param name="pos">pos is pointing the middle connecting key in between the left and right.</param>
		/// <param name="left"></param>
		/// <param name="right"></param>
		public void RedistributeRight2Left(int pos, BNode left, BNode right)
		{
			Debug.Assert(pos >=0 && pos < m_keys.Length);
			Debug.Assert(m_children[pos] == left.SegmentID);
			Debug.Assert(m_children[pos+1] == right.SegmentID);
			Debug.Assert(m_keys[pos].CompareTo(left.m_keys[left.m_keyNums-1])>0);
			Debug.Assert(m_keys[pos].CompareTo(right.m_keys[right.m_keyNums-1])<0);

			//copy middle key in parent to tail of left
			left.m_keys[left.m_keyNums++] = m_keys[pos];
			left.m_children[left.m_keyNums] = right.m_children[0]; //move first pointer in right to be the last in new left
            
			//replace the middle key with the first key in right
			m_keys[pos] = right.m_keys[0];

			//remove the first key along with the first pointer from right
			for (int i=1; i<right.KeyNums; i++)
			{
				right.m_keys[i-1] = right.m_keys[i];
				right.m_children[i-1] = right.m_children[i];
			}
			right.m_keyNums --;
			//move the last one
			right.m_children[right.m_keyNums] = right.m_children[right.m_keyNums+1];

			this.m_dirty = true;
			left.m_dirty = true;
			right.m_dirty = true;
		}
예제 #12
0
파일: BNode.cs 프로젝트: luanzhu/OOD.NET
		/// <summary>
		/// Split the internal node with the newKey which is trying to insert this internal node
		/// </summary>
		/// <param name="newKey"></param>
		/// <param name="pos"></param>
		/// <param name="right"></param>
		/// <param name="newMedian"></param>
		/// <param name="newRight"></param>
		public void SplitAtInternal(IKey newKey, int pos, uint rightSon, out IKey newMedian, BNode newRight)
		{
			Debug.Assert(this.m_leaf == false);
			Debug.Assert(this.IsFull);

			IKey[] temp = new IKey[m_order];
			uint[] t_pointer = new uint[m_order + 1];

			//copy old data into new arrays
			Array.Copy(m_keys, 0, temp, 0, m_order-1);
			Array.Copy(m_children, 0, t_pointer, 0, m_order);

			//shift everything after this key right
			for (int i=this.m_keyNums; i>pos; i--)
			{
				temp[i] = temp[i-1];
				t_pointer[i+1] = t_pointer[i];
			}

			temp[pos] = newKey;
			t_pointer[pos+1] = rightSon;

			//copy left half back this node
			int mid = m_order >> 1;

			Array.Copy(temp,0,m_keys,0,mid);
			Array.Copy(t_pointer,0,m_children,0,mid+1);

			newMedian = temp[mid];

			Array.Copy(temp,mid+1,newRight.m_keys,0,m_order-mid-1);
			Array.Copy(t_pointer,mid+1,newRight.m_children,0,m_order-mid);

			m_keyNums = (short)mid;
            newRight.m_keyNums = (short)(m_order - mid -1);

			this.m_dirty = true;
			newRight.m_dirty = true;
		}
예제 #13
0
파일: BNode.cs 프로젝트: luanzhu/OOD.NET
		/// <summary>
		/// split the leaf into two, leave left half in current leaf, and move right half into right node
		/// </summary>
		/// <param name="newKey"></param>
		/// <param name="median">the middle key is popped up</param>
		/// <param name="right"></param>
		public void SplitAtLeaf(IKey newKey, int pos, ref IKey median, ref BNode right)
		{
			Debug.Assert(this.m_leaf);
			Debug.Assert(this.IsFull);

			right.SetOrder(this.m_order);
			right.m_leaf = this.m_leaf;
			
			int mid = m_order >> 1;

			//copy current keys into a bigger array
			IKey[] temp = new IKey[m_order];
			Array.Copy(m_keys,0,temp,0,m_order - 1);
			//insert the newKey into the pos location
			//shift later keys to the right
			for (int i=this.m_keyNums; i>pos; i--)
			{
				temp[i] = temp[i-1];
			}

			temp[pos] = newKey;

			median = temp[mid];

			//copy left half to current leaf
			for (int i=0; i<mid; i++)
			{
				m_keys[i] = temp[i];
			}
			//copy right half to right leaf
			for (int i=mid+1; i<temp.Length; i++)
			{
				right.m_keys[i-mid-1] = temp[i];
			}

			m_keyNums = (short)mid;
			right.m_keyNums = (short)(m_order - 1 - mid);

			this.m_dirty = true;
			right.m_dirty = true;
		}
예제 #14
0
        /// <summary>
        /// Create the internal storage for the dbFile.
        /// Note:
        ///   1. a helper file for segment managment b-tree is also created if this database file
        ///      does not exist.
        /// </summary>
        /// <param name="dbFile"></param>
        public ObjectStore(string dbFileName)
        {
            m_dbFile           = new DiskFile(dbFileName);
            m_indexFile        = new DiskFile(dbFileName + ".idx");
            m_indexPageManager = new memSegmentManager(m_indexFile);

            if (m_indexPageManager.Header.InitializeNeeded)
            {
                m_indexPageManager.Header.NextSegmentId = 0;
                m_indexPageManager.Header.NextObjectId  = 0;
                m_indexPageManager.Header.NextClassId   = 0;

                //initialize the segment b-tree's top node id
                OOD.Imp.Storage.BNode segTreeTop = new OOD.Imp.Storage.BNode();
                m_indexPageManager.GetNewSegment(segTreeTop);
                segTreeTop.SetOrder(m_segTreeNodeOrder);
                segTreeTop.Leaf = true;
                m_indexPageManager.Header.SegmentTreeTopNodeSId = segTreeTop.SegmentID;

                //initialize the space b-tree's top node id
                BNode spaceTreeTop = new BNode();
                m_indexPageManager.GetNewSegment(spaceTreeTop);
                spaceTreeTop.SetOrder(m_spaceTreeNodeOrder);
                spaceTreeTop.Leaf = true;
                m_indexPageManager.Header.FreeSpaceTreeTopNodeSId = spaceTreeTop.SegmentID;
            }

            m_segmentIndexTree = new SegTree(m_indexPageManager.Header.SegmentTreeTopNodeSId, m_indexPageManager);
            m_spaceIndexTree   = new SpaceTree(m_indexPageManager.Header.FreeSpaceTreeTopNodeSId, m_indexPageManager, m_dbFile);

            m_dbSegmentManager = new dbSegmentManager(
                m_indexPageManager.Header.NextSegmentId,
                m_segmentIndexTree,
                m_spaceIndexTree,
                m_dbFile);


            if (m_indexPageManager.Header.InitializeNeeded)
            {
                BNode catalogTop = new BNode();
                m_dbSegmentManager.GetNewSegment(catalogTop);
                catalogTop.SetOrder(m_catalogTreeNodeOrder);
                catalogTop.Leaf = true;

                m_indexPageManager.Header.CatalogTreeTopNodeSId = catalogTop.SegmentID;
            }

            m_catalogTree = new CatalogTree(
                m_indexPageManager.Header.CatalogTreeTopNodeSId,
                m_dbSegmentManager,
                m_indexPageManager.Header.NextClassId);

            m_classCache      = new LRUHashtable(m_cache_size, m_classCacheLimit);
            m_objectTreeCache = new LRUHashtable(m_cache_size, m_objectTreeCacheLimit);

            //bring top node's segment tree, space tree, catalog tree into cache, they will be needed anyway
            if (!m_indexPageManager.Header.InitializeNeeded)
            {
                m_indexPageManager.GetSegment(m_segmentIndexTree.TopNodSegId, new BNode(), new KSegId());
                m_indexPageManager.GetSegment(m_spaceIndexTree.TopNodeSId, new BNode(), new KOffset());
                m_dbSegmentManager.GetSegment(m_catalogTree.TopNodeSId, new BNode(), new KCatalog());
            }
        }
예제 #15
0
        /// <summary>
        /// Remove the key from the tree.
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool Delete(IKey key)
        {
            int pos = -1;

            System.Collections.Stack visited  = new System.Collections.Stack();
            System.Collections.Stack viaLinks = new System.Collections.Stack();

            //find the node which contains the key
            BNode n = FindNode(m_top, key, ref pos, visited, viaLinks);

            if (n == null)
            {
                return(false);
            }
            else
            {
                if (n.Leaf)
                {
                    n.RemoveAtLeaf(key, pos);
                }
                else
                {
                    visited.Push(n);
                    uint nextNodeId = n.GetChildAt(pos + 1);
                    viaLinks.Push(pos + 1);
                    BNode t_node = (BNode)m_sgManager.GetSegment(nextNodeId, m_nodeFactory, m_keyFactory);
                    //find the leaf most leaf in its right sub-tree
                    while (!t_node.Leaf)
                    {
                        visited.Push(t_node);
                        nextNodeId = t_node.GetChildAt(0);
                        viaLinks.Push(0);
                        t_node = (BNode)m_sgManager.GetSegment(nextNodeId, m_nodeFactory, m_keyFactory);
                    }
                    Debug.Assert(t_node.Leaf);

                    IKey successor = t_node.GetKeyAt(0);

                    //replace the key&data in n with the successor
                    n.ReplaceKeyDataWSuccessor(key, successor, pos);

                    //remove successor from the leaf node
                    t_node.RemoveAtLeaf(successor, 0);

                    n = t_node;
                }
            }

            //now n is the leaf node where the real deletion happens
            //visited keep all the parents visited so far, viaLinks keeps which links we followed
            while (n.IsUnderflow && n.SegmentID != m_top_sid)
            {
                BNode parent = (BNode)visited.Pop();
                //get left/right brother
                int   followed = (int)viaLinks.Pop();
                BNode left     = (followed > 0? (BNode)m_sgManager.GetSegment(parent.GetChildAt(followed - 1), m_nodeFactory, m_keyFactory) : null);
                BNode right    = (followed < parent.KeyNums ? (BNode)m_sgManager.GetSegment(parent.GetChildAt(followed + 1), m_nodeFactory, m_keyFactory) : null);

                Debug.Assert(left != null || right != null);

                bool combined = false;
                //try combin with right first
                if (right != null && right.KeyNums == right.ReqMinimum)
                {
                    //combine with the right
                    parent.CombineChildren(followed, n, right);
                    Debug.Assert(right.KeyNums == 0);
                    Debug.Assert(n.KeyNums > n.ReqMinimum);
                    m_sgManager.FreeSegment(right);

                    combined = true;

                    if (parent.KeyNums == 0)
                    {
                        Debug.Assert(parent.Leaf == false);
                        Debug.Assert(parent.SegmentID == this.m_top_sid);
                        //tree will shrink
                        this.m_top_sid = n.SegmentID;
                        m_sgManager.FreeSegment(parent);
                        break;
                    }
                }
                else if (left != null && left.KeyNums == left.ReqMinimum)
                {
                    //combine with the left
                    parent.CombineChildren(followed - 1, left, n);
                    Debug.Assert(n.KeyNums == 0);
                    Debug.Assert(left.KeyNums > left.ReqMinimum);
                    m_sgManager.FreeSegment(n);

                    combined = true;

                    if (parent.KeyNums == 0)
                    {
                        Debug.Assert(parent.Leaf == false);
                        Debug.Assert(parent.SegmentID == this.m_top_sid);
                        //tree will shrink
                        this.m_top_sid = left.SegmentID;
                        m_sgManager.FreeSegment(parent);
                        break;
                    }
                }
                if (!combined)
                {
                    //try redistrubute if combine is not possible
                    if (right != null && right.KeyNums > right.ReqMinimum)
                    {
                        //redistribute one entry from right node
                        parent.RedistributeRight2Left(followed, n, right);
                    }
                    else if (left != null && left.KeyNums > left.ReqMinimum)
                    {
                        //redistribute with left
                        parent.RedistributeLeft2Right(followed - 1, left, n);
                    }
                }

                else
                {
                    n = parent;
                }
            }

            return(true);
        }
예제 #16
0
        /// <summary>
        /// Insert the newKey into this B-tree,
        /// </summary>
        /// <param name="newKey"></param>
        /// <returns></returns>
        public bool Insert(IKey newKey)
        {
            //find the leaf where the newKey should be in
            BNode n = m_top;

            System.Collections.Stack visited = new System.Collections.Stack();
            int pos = -1;

            while (!n.Leaf)
            {
                IKey temp = n.SearchKey(newKey, ref pos);
                if (temp == null)
                {
                    uint nextNodeId = n.GetChildAt(pos);
                    visited.Push(n);

                    n = (BNode)m_sgManager.GetSegment(nextNodeId, m_nodeFactory, m_keyFactory);
                }
                else
                {
                    return(false);
                }
            }

            //now BNode n is the leaf where insert should happen
            IKey t_temp = n.SearchKey(newKey, ref pos);

            if (t_temp == null)
            {
                //not exists, go ahead to insert the new key
                if (!n.IsFull)
                {
                    n.InsertAtLeaf(newKey, pos);

                    return(true);
                }
                else
                {
                    //split needed for this node
                    BNode right = new BNode();
                    m_sgManager.GetNewSegment(right);
                    IKey median = null;
                    n.SplitAtLeaf(newKey, pos, ref median, ref right);                      //this split is at leaf

                    bool finished = false;
                    //now n holds the left half of the items,
                    //right holds the right half items, median is the middle key

                    while (!finished)
                    {
                        //parent is node middle key will be inserted
                        BNode parent = (visited.Count > 0 ? (BNode)visited.Pop() : null);

                        if (parent == null)
                        {
                            //new top node is needed
                            BNode new_top = new BNode();
                            m_sgManager.GetNewSegment(new_top);
                            new_top.SetOrder(m_top.Order);
                            new_top.Leaf = false;
                            new_top.InsertFirstKey(median, n.SegmentID, right.SegmentID);

                            this.m_top_sid = new_top.SegmentID;

                            return(true);
                        }
                        else
                        {
                            IKey tt = parent.SearchKey(median, ref pos);
                            if (tt != null)
                            {
                                return(false);
                            }

                            if (!parent.IsFull)
                            {
                                parent.InsertAtInternal(median, pos, right.SegmentID);
                                return(true);
                            }
                            else
                            {
                                //parent is full again
                                BNode newRight = new BNode();
                                m_sgManager.GetNewSegment(newRight);
                                newRight.SetOrder(parent.Order);
                                newRight.Leaf = parent.Leaf;
                                //this split will insert median into the parent, then split and new middle key is newMedian
                                IKey newMedian;
                                parent.SplitAtInternal(median, pos, right.SegmentID, out newMedian, newRight);

                                n      = parent;
                                median = newMedian;
                                right  = newRight;
                            }
                        }
                    }
                }
            }
            else
            {
                return(false);
            }

            return(false);
        }