/////////////////////////////////////////////////////////////////////////////////////////////////// //-- void BPTree::insert_entry(_F_FileAddr L, pKey_Attr pPrimKey, _F_FileAddr pRec) { BPTreeNode NodeL; NodeL.readNodeFromFile(L); //if L has less than n-1 key values if(NodeL.ItemOnNode < NodeL.MaxItem) { if(NodeL.IsLeaf ==1) NodeL.insertKeyInLeaf(pRec, pPrimKey); else NodeL.insertKeyNotLeaf(pPrimKey, pRec); } else { //create a new node _F_FileAddr L_ = createNodeInFile(); BPTreeNode NodeL_; pKey_Attr pPrimKey_; int n = NodeL.MaxItem + 1; if(NodeL.IsLeaf ==1) { NodeL_.IsLeaf = 1; int m; if( !(n%2) ) m = n/2 ; else m = n/2 + 1; //p[0]k[0]...k[m-1]p[m] | k[m]... // pPrimKey < k[m-1] if( NodeL.compare(NodeL.k[m-1], pPrimKey) > 0) { m--; pPrimKey_ = NodeL.createKey(NodeL.k[m]); } // k[m] > pPrimKey >= k[m-1] else if( (m == n - 1) || ( NodeL.compare(NodeL.k[m], pPrimKey) > 0 ) ) pPrimKey_ = NodeL.createKey(pPrimKey); else // pPrimKey > k[m] pPrimKey_ = NodeL.createKey(NodeL.k[m]); //copy p[m]....to L_ for(int i=m; i<NodeL.MaxItem; i++) { NodeL_.p[i-m] = NodeL.p[i]; NodeL_.k[i-m] = NodeL.k[i]; //erase NodeL.k[i] = NULL; NodeL.p[i].ulFilePageID = 0; NodeL.p[i].uiOffset = 0; NodeL_.ItemOnNode++; NodeL.ItemOnNode--; } if(NodeL.compare(pPrimKey, pPrimKey_) < 0) NodeL.insertKeyInLeaf(pRec,pPrimKey); else NodeL_.insertKeyInLeaf(pRec,pPrimKey); } else { //NodeL is not a leaf NodeL_.IsLeaf = 0; int m; if( !(n%2) ) m = n/2 ; else m = n/2 + 1; m = NodeL.MaxItem - m; //p[0],k[0]....k[m]p[m+1] | k[m+1]... //pPrimKey > k[m+1] if( NodeL.compare(pPrimKey, NodeL.k[m+1]) > 0 ) { m++; pPrimKey_ = NodeL.createKey(NodeL.k[m]); } // k[m] < pPrimKey <= k[m+1] else if( NodeL.compare(pPrimKey, NodeL.k[m]) > 0 ) { m++; pPrimKey_ = NodeL.createKey(pPrimKey); } // pPrimKey <= k[m] else { pPrimKey_ = NodeL.createKey(NodeL.k[m]); } // move and delete NodeL_.p[0].ulFilePageID = 0; NodeL_.p[0].uiOffset = 0; NodeL_.k[0] = NodeL.k[m]; NodeL.k[m] = NULL; NodeL_.ItemOnNode++; NodeL.ItemOnNode--; for(int i=m+1; i<NodeL.MaxItem; i++) { NodeL_.p[i-m] = NodeL.p[i]; NodeL_.k[i-m] = NodeL.k[i]; //erase NodeL.k[i] = NULL; NodeL.p[i].ulFilePageID = 0; NodeL.p[i].uiOffset = 0; NodeL_.ItemOnNode++; NodeL.ItemOnNode--; } NodeL_.p[i-m] = NodeL.p[i]; NodeL.p[i].ulFilePageID = 0; NodeL.p[i].uiOffset = 0; if( NodeL.compare(pPrimKey, pPrimKey_) < 0 ) NodeL.insertKeyNotLeaf(pPrimKey, pRec); else NodeL_.insertKeyNotLeaf(pPrimKey,pRec); NodeL_.deleteFirstKey(); } if( !isRoot(L) ) insert_entry(getParent(L), pPrimKey_, L_); else createNewRoot(L, pPrimKey_, L_); if(NodeL.IsLeaf == 1) { NodeL_.p[NodeL.MaxItem] = NodeL.p[NodeL.MaxItem]; NodeL.p[NodeL.MaxItem] = L_; } NodeL_.writeNodeToFile(L_); } NodeL.writeNodeToFile(L); }
bool BTree<K, Comp>::insert(K key, uint64_t tid) { //latch the root BufferFrame* curFrame = &bufferManager.fixPage(rootPID, true); Node<K, Comp>* curNode = reinterpret_cast<Node<K, Comp>*>(curFrame->getData()); BufferFrame* parFrame = NULL; while (!curNode->isLeaf()) { if (curNode->count >= maxNodeSize) { // --> split to safe inner pages if (parFrame == NULL) { //Need to create a new root (parent) first parFrame = createNewRoot(); } BufferFrame* newFrame = &bufferManager.fixPage(nextFreePage++, true); K splitKey = curNode->split(curFrame->pageId, newFrame, parFrame, smaller); //determine correct node and release the other one if (smaller(key, splitKey)) { bufferManager.unfixPage(*newFrame, true); } else { curNode = reinterpret_cast<Node<K, Comp>*>(newFrame->getData()); bufferManager.unfixPage(*curFrame, true); curFrame = newFrame; } } //release the parent node if (parFrame != NULL) { bufferManager.unfixPage(*parFrame, true); //TODO only set true when parent is really dirty? } parFrame = curFrame; //latch the next level uint64_t pos = curNode->findKeyPos(key, smaller); uint64_t nextPID = (pos == curNode->count) ? curNode->next : curNode->keyValuePairs[pos].second; curFrame = &bufferManager.fixPage(nextPID, true); curNode = reinterpret_cast<Node<K, Comp>*>(curFrame->getData()); } Node<K, Comp>* leaf = reinterpret_cast<Node<K, Comp>*>(curNode); if (leaf->count >= maxNodeSize) { if (parFrame == NULL) { parFrame = createNewRoot(); } BufferFrame* newFrame = &bufferManager.fixPage(nextFreePage++, true); K splitKey = leaf->split(curFrame->pageId, newFrame, parFrame, smaller); if (smaller(key, splitKey)) { bufferManager.unfixPage(*newFrame, true); } else { leaf = reinterpret_cast<Node<K, Comp>*>(newFrame->getData()); bufferManager.unfixPage(*curFrame, true); curFrame = newFrame; } } if (parFrame != NULL) { bufferManager.unfixPage(*parFrame, true); //TODO: only mark dirty when parent was actually updated } bool insertSuccessful = leaf->insertKey(key, tid, smaller); if (insertSuccessful) { elements++; } bufferManager.unfixPage(*curFrame, true); return insertSuccessful; }