/// <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; }
/// <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()); } }
/* 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; }
/// <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; }
/// <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; }
/// <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()); } }
/// <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); }