BPTree.cpp
上传用户:lkd6667
上传日期:2015-05-13
资源大小:1448k
文件大小:43k
源码类别:

其他数据库

开发平台:

C/C++

  1. //!BPTree.cpp   2007/6/28
  2. #include "BPtree.h"
  3. #include "Glob_Var.h"
  4. extern unsigned int BTreeNodeSize;
  5. extern _M_Buffer Buffer;
  6. extern unsigned int  SizeOfPageHead;
  7. extern char CurLocation[256];
  8. extern char CurRelationName[33];
  9. /*=========================================================================
  10. =========             definition for BPTree_Index             =============
  11. =========================================================================*/
  12. /////////////////////////////////////////////////////////////////////////////////////////////////////////
  13. //constructor and destructor
  14. BPTree_Index::BPTree_Index() { 
  15. }
  16. BPTree_Index::~BPTree_Index(){
  17. }
  18. /////////////////////////////////////////////////////////////////////////////////////////////////////////
  19. void BPTree_Index::createHead(char* KeyStr) {
  20.   setKeyInfo(KeyStr);    // calculate the Keysize and KeyAttrNum
  21.   // calculate the MaxItemNum in a node
  22.   // Next_Empty_Block | IsLeaf | ItemOnNode | p[0],k[0],...,p[MaxItemNum] 
  23.   IdxHead.MaxItemNum = ( BTreeNodeSize - 2*sizeof(_F_FileAddr) - sizeof(bool) - sizeof(int) ) 
  24.                        / ( sizeof(_F_FileAddr) + IdxHead.KeySize );
  25.   
  26.   //no empty block
  27.   IdxHead.FirstEmptyBlock.ulFilePageID = 0;
  28.   IdxHead.FirstEmptyBlock.uiOffset     = 0; 
  29.   IdxHead.LastEmptyBlock.ulFilePageID  = 0;
  30.   IdxHead.LastEmptyBlock.uiOffset      = 0;
  31.   
  32.   //the first address of the BTree node
  33.   IdxHead.FirstNewBlock.ulFilePageID = 1;
  34.   IdxHead.FirstNewBlock.uiOffset     = SizeOfPageHead + BTreeNodeSize;
  35.   // initialize the root address 
  36.   IdxHead.root.ulFilePageID = 1;
  37.   IdxHead.root.uiOffset     = SizeOfPageHead;
  38.   
  39.   // the start node isn't existed
  40.   IdxHead.start.ulFilePageID = 0;
  41.   IdxHead.start.uiOffset     = 0;
  42.   // the key information
  43.   KeyInfo = KeyStr;
  44. }
  45. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  46. // write the infomation to the head of the btree index file
  47. void BPTree_Index::writeHeadToFile() {
  48.   // get the start address which store the head
  49.   char address[256];
  50.   strcpy(address,CurLocation);
  51.   strcat(address,CurRelationName);
  52.   strcat(address,".idx");
  53.   _M_File test = Buffer[address];  
  54.   _F_FileAddr ptr = test.GetIdxPoint();
  55.   // write IdxHead
  56.   void* temp = (void*)(&IdxHead);
  57.   _F_FileAddr next;
  58.   next = MemWrite( temp,sizeof(Index_Head),&ptr);
  59.  
  60.   // write Key information
  61.   temp = (void*)KeyInfo;
  62.   
  63.   MemWrite(temp,strlen(KeyInfo) + 1,&next);
  64. }
  65. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  66. // read the infomation from the head of the btree index file
  67. void BPTree_Index::readHeadFromFile() {
  68.   // get the start address which store the head
  69.   char address[256];
  70.   strcpy(address,CurLocation);
  71.   strcat(address,CurRelationName);
  72.   strcat(address,".idx");
  73.   _M_File test = Buffer[address];  
  74.   _F_FileAddr ptr = test.GetIdxPoint();
  75.   // read IdxHead
  76.   Index_Head* temp;
  77.   temp = (Index_Head*) ( ptr.MemAddr() );
  78.   IdxHead = *temp;
  79.   // read key information
  80.   ptr.ShiftOffset(sizeof(Index_Head));
  81.   KeyInfo = (char*) (ptr.MemAddr());
  82.  
  83. }
  84.  
  85. ////////////////////////////////////////////////////////////////////////////////////////////////////////////
  86. // calculate the KeySize and count the KeyAttrNum
  87. void BPTree_Index::setKeyInfo(char* KeyStr) {
  88.   IdxHead.KeyAttrNum = 0;  // the number of fields(attributes) in primary key
  89.   IdxHead.KeySize    = 0;    // sizeof(Key_Attr) * KeyAttrNum
  90.   char* temp = KeyStr;
  91.   for( int i=0; temp[i]!=0; i++)
  92.   {
  93.     IdxHead.KeyAttrNum++;
  94.     switch(temp[i])
  95.     {
  96.       case 'i' : IdxHead.KeySize += sizeof(int);     break;
  97.       case 'f' : IdxHead.KeySize += sizeof(float);   break;
  98.       case 'c' : {
  99.                    //deal with the max length in a string defined by the user
  100.                    int num = 0;
  101.                    for( i=i+1; isdigit(temp[i]); i++)
  102.                    {
  103.                      num = num * 10 + temp[i] - '0';
  104.                    }
  105.                    i--;        // move the index back
  106.                    num++;      // for '' which is the end of a string
  107.                    IdxHead.KeySize += num;
  108.                    break;
  109.                  }
  110.       default  : throw(1021); 
  111.     }
  112.   }
  113. }
  114. // /////////////////////////////////////////////////////////////////////////////////////////////////////////
  115. int BPTree_Index::getKeySize() {
  116.   return IdxHead.KeySize;
  117. }
  118. int BPTree_Index::getKeyAttrNum() {
  119.   return IdxHead.KeyAttrNum;
  120. int BPTree_Index::getMaxItemNum() {
  121.   return IdxHead.MaxItemNum;
  122. }
  123.  
  124. _F_FileAddr BPTree_Index::getRoot() {
  125.   return IdxHead.root;
  126. }
  127. _F_FileAddr BPTree_Index::getStartNode() {
  128.   return IdxHead.start;
  129. }
  130. char* BPTree_Index::getKeyInfo() {
  131.   return KeyInfo;
  132. }
  133. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  134. /*=========================================================================
  135. =========              definition for BPTreeNode              =============
  136. =========================================================================*/
  137. /////////////////////////////////////////////////////////////////////////////////////////////
  138. // initialize the node 
  139. BPTreeNode::BPTreeNode() {
  140.   // read the head of the file
  141.   BPTree_Index temp;
  142.   temp.readHeadFromFile();
  143.   MaxItem    = temp.getMaxItemNum();  // get the MaxItem
  144.   KeyInfo    = temp.getKeyInfo();     // get the KeyInfo
  145.   KeySize    = temp.getKeySize();     // get the size of key
  146.   ItemOnNode = 0;                     // the key number is 0
  147.   
  148.   p = new _F_FileAddr[MaxItem+1];
  149.   for(int i=0;i<MaxItem+1;i++)
  150.   {
  151.     p[i].ulFilePageID = 0;
  152.     p[i].uiOffset     = 0;
  153.   }
  154.   k = new pKey_Attr[MaxItem];
  155.   for(int j=0;j<MaxItem;j++)
  156.     k[j] = NULL; 
  157. }
  158. ///////////////////////////////////////////////////////////////////////////////////////////////
  159. void BPTreeNode::initialize() {
  160.   for(int j=0;j<ItemOnNode;j++)
  161.     k[j] = NULL; 
  162.   ItemOnNode = 0;
  163. }
  164. ///////////////////////////////////////////////////////////////////////////////////////////////
  165. // write the separate space into one block
  166. // MemPtr is the first address of the block
  167. void BPTreeNode::writeNodeToFile(_F_FileAddr ptr) {
  168.   void* MemPtr;
  169.   MemPtr = ptr.MemAddr();
  170.   
  171.   // write Next_Empty_Block into the block
  172.   MemWrite((void*)(&Next_Empty_Block),sizeof(_F_FileAddr),&ptr);
  173.   // move to the first address of IsLeaf
  174.   MemPtr = (void*)((char*)MemPtr + sizeof(_F_FileAddr));
  175.   
  176.   // write IsLeaf into the block
  177.   bool* pIsLeaf = (bool*)MemPtr;
  178.   *pIsLeaf      = IsLeaf;
  179.        
  180.   // move to the first address of ItemNode in the block
  181.   MemPtr = (void*)((char*)MemPtr + sizeof(bool));
  182.   // write ItemOnNode into the block
  183.   int *pItemOnNode = (int*)MemPtr;
  184.   *pItemOnNode     = ItemOnNode;
  185.   // move the the first address of p[o] in the block
  186.   MemPtr = (void*)((char*)MemPtr + sizeof(int));
  187.   int i;
  188.   for(i=0;i<ItemOnNode;i++)
  189.   {
  190.     // write the p[i]
  191.     _F_FileAddr* pp    = (_F_FileAddr*)MemPtr;
  192.     pp->ulFilePageID = p[i].ulFilePageID;
  193.     pp->uiOffset     = p[i].uiOffset;
  194.     // move to the first address of k[i] in the block
  195.     MemPtr = (void*)((char*)MemPtr + sizeof(_F_FileAddr));
  196.     
  197.     // write the k[i]
  198.     pKey_Attr pField = k[i];
  199.     for(int j=0;KeyInfo[j]!=0;j++)
  200.     {
  201.       switch(KeyInfo[j])
  202.       {
  203.         
  204.         case 'i'   :  // int value
  205.                       int *pIntValue;
  206.                       pIntValue = (int*)MemPtr;
  207.                       *pIntValue     = pField->value.IntValue;
  208.                       pField         = pField->next;
  209.                       MemPtr = (void*)((char*)MemPtr + sizeof(int));
  210.                       break;
  211.         case 'f'   :  // float value
  212.                       float *pFloatValue; 
  213.                       pFloatValue = (float*)MemPtr;
  214.                       *pFloatValue       = pField->value.FloatValue;
  215.                       pField             = pField->next;
  216.                       MemPtr = (void*)((char*)MemPtr + sizeof(float));
  217.                       break;
  218.         case 'c'   :  // string
  219.                       int num = 0;
  220.                       for(j=j+1; isdigit(KeyInfo[j]);j++)
  221.                       {
  222.                         num = num * 10 + KeyInfo[j] - '0';
  223.                       }
  224.                       j--;        // move the index back
  225.                       num++;      // for '' which is the end of a string
  226.                       char* pCharValue = (char*)MemPtr;
  227.                       strcpy(pCharValue,pField->value.pCharValue);
  228.                       pField = pField->next;
  229.                       MemPtr = (void*)((char*)MemPtr + num);
  230.                       break;                      
  231.       }
  232.     }// KeyInfo[i] = ''
  233.   }// i = ItemOnNode
  234.   if( 0 == IsLeaf) // not a leaf
  235.   {
  236.     //Write the p[ItemOnNode]
  237.     _F_FileAddr* pp = (_F_FileAddr*)MemPtr;
  238.     pp->ulFilePageID = p[i].ulFilePageID;
  239.     pp->uiOffset     = p[i].uiOffset;
  240.   }
  241.   else // is is a leaf
  242.   {
  243.     // move to the address of p[MaxItem]
  244.     MemPtr = (void*)( (char*)MemPtr + (MaxItem - ItemOnNode) * (KeySize + sizeof(_F_FileAddr)) );
  245.     //Write the p[MaxItem] into the block
  246.     _F_FileAddr* pp = (_F_FileAddr*)MemPtr;
  247.     pp->ulFilePageID = p[MaxItem].ulFilePageID;
  248.     pp->uiOffset     = p[MaxItem].uiOffset;
  249.   }
  250. }
  251. ///////////////////////////////////////////////////////////////////////////////////////////////
  252. // the struct of node
  253. // NodeType | ItemOnNode | p[0],k[0],p[1],k[1],......,p[MaxItem-1],k[MaxItem-1],p[MaxItem]
  254. void BPTreeNode::readNodeFromFile(_F_FileAddr ptr) {
  255.   // move to the address of NodeType
  256.   void* temp     = ptr.MemAddr();
  257.   // get the Next_Empty_Block
  258.   _F_FileAddr* pNext = (_F_FileAddr*)temp;
  259.   Next_Empty_Block.ulFilePageID = pNext->ulFilePageID;
  260.   Next_Empty_Block.uiOffset     = pNext->uiOffset;
  261.   // move to the address of NodeType
  262.   temp = (void*)((char*)temp + sizeof(_F_FileAddr));
  263.   // get the NodeType
  264.   bool* pIsLeaf = (bool*)temp;
  265.   IsLeaf        = *pIsLeaf;
  266.   // move to the address of ItemOnNode
  267.   temp = (void*)((char*)temp + sizeof(bool));
  268.   
  269.   // get the ItemOnNode
  270.   int* pItemOnNode = (int*)temp;
  271.   ItemOnNode       = *pItemOnNode;
  272.   // move to the first address of p[0]
  273.   temp = (void*)((char*)temp + sizeof(int));
  274.   // read p[i] and k[i]
  275.   int i;
  276.   for(i=0;i<ItemOnNode;i++)
  277.   {
  278.     // get the p[i]
  279.     _F_FileAddr* pp;
  280.     pp = (_F_FileAddr*)temp;
  281.     p[i].ulFilePageID = pp->ulFilePageID;
  282.     p[i].uiOffset     = pp->uiOffset;
  283.     // move to the first address of k[i] in the block
  284.     temp = (void*)((char*)temp + sizeof(_F_FileAddr));
  285.         
  286.     // get the k[i]
  287.     pKey_Attr pField;
  288.     for(int j=0; KeyInfo[j]!='';j++)
  289.     {
  290.       if(j == 0)    // the first node
  291.         pField = k[i] = new Key_Attr;
  292.       else
  293.       {
  294.         pField->next = new Key_Attr;
  295.         pField       = pField->next;
  296.       }
  297.       switch(KeyInfo[j])
  298.       {
  299.         case 'i'  :  // int value  
  300.                      int* pIntValue;
  301.                      pIntValue              = (int*) temp;
  302.                      pField->value.IntValue = *pIntValue;
  303.                      pField->next           = NULL;
  304.                      temp = (void*)((char*)temp + sizeof(int));
  305.                      break;
  306.         case 'f'  :  // float value 
  307.                      float* pFloatValue;
  308.                      pFloatValue              = (float*) temp;
  309.                      pField->value.FloatValue = *pFloatValue;
  310.                      pField->next             = NULL;
  311.                      temp = (void*)((char*)temp + sizeof(float));
  312.                      break;
  313.         case 'c'  :  // string
  314.                      int num = 0;
  315.                      for( j=j+1; isdigit(KeyInfo[j]); j++)
  316.                      {
  317.                        num = num * 10 + KeyInfo[j] - '0';
  318.                      }
  319.                      j--;        // move the index back
  320.                      num++;      // for '' which is the end of a string
  321.                      char* pCharValue = new char [num];
  322.                      char* str = (char*)temp;
  323.                      strcpy(pCharValue,str);
  324.                      pField->value.pCharValue = pCharValue;
  325.                      pField->next             = NULL;
  326.                      temp = (void*)((char*)temp + num);
  327.                      break;                  
  328.       }
  329.     }  //KeyInfo[i] = ''
  330.   } // i = ItemOnNode
  331.   if( 0 == IsLeaf)
  332.   {
  333.     // get the p[ItemOnNode]
  334.     _F_FileAddr* pp;
  335.     pp = (_F_FileAddr*)temp;
  336.     p[i].ulFilePageID = pp->ulFilePageID;
  337.     p[i].uiOffset     = pp->uiOffset;
  338.   }
  339.   else
  340.   {
  341.     // move to the address of p[MaxItem]
  342.     temp = (void*)( (char*)temp + (MaxItem - ItemOnNode) * (KeySize + sizeof(_F_FileAddr)) );
  343.     // get the p[MaxItem]
  344.     _F_FileAddr* pp;
  345.     pp = (_F_FileAddr*)temp;
  346.     p[MaxItem].ulFilePageID = pp->ulFilePageID;
  347.     p[MaxItem].uiOffset     = pp->uiOffset;
  348.   }
  349.     
  350. }
  351. ///////////////////////////////////////////////////////////////////////////////////////////////
  352. // delete the space allocate for the node
  353. BPTreeNode::~BPTreeNode() {
  354.   // delete the link list of keys
  355.   for(int i=0;i<ItemOnNode;i++)
  356.   {
  357.     pKey_Attr head,temp;
  358.     head = temp = k[i];
  359.     for(int j=0;KeyInfo[j]!=0;j++)
  360.     {
  361.       switch(KeyInfo[j])
  362.       {
  363.         case 'i' :  // int 
  364.                     head = head->next;
  365.                     delete temp;
  366.                     temp = head;
  367.                     break;
  368.         case 'f' :  // float
  369.                     head = head->next;
  370.                     delete temp;
  371.                     temp = head;
  372.                     break;
  373.         case 'c' :  // char
  374.                     delete  [] (head->value.pCharValue);
  375.                     head = head->next;
  376.                     delete temp;
  377.                     temp = head;
  378.                     while(isdigit(KeyInfo[++j])) ;  //skip digital number
  379.                     j--;
  380.                     break;
  381.       }
  382.     }
  383.   }
  384.   // detele the array of p and k
  385.   delete [] p ;
  386.   delete [] k;
  387. }
  388. ///////////////////////////////////////////////////////////////////////////////////////////////
  389. // compare the key1 and key2
  390. // if Key1 is greater than key2,return 1
  391. // if key1 is equal with key2, return 0
  392. // if key1 is less than key2,return -1
  393. int BPTreeNode::compare(pKey_Attr Key1,pKey_Attr Key2) {
  394.    
  395.   for(int i=0;KeyInfo[i]!='';i++)
  396.   {
  397.     switch(KeyInfo[i])
  398.     {
  399.   case 'i' :
  400.                if(Key1->value.IntValue > Key2->value.IntValue)
  401.                  return 1;
  402.                else if(Key1->value.IntValue < Key2->value.IntValue)
  403.                  return -1;
  404.                else
  405.                  break;
  406.       case 'f' : 
  407.                if(Key1->value.FloatValue > Key2->value.FloatValue)
  408.                  return 1;
  409.                else if(Key1->value.FloatValue < Key2->value.FloatValue)
  410.                  return -1;
  411.                else
  412.                  break;
  413.       case 'c' :
  414.                while(isdigit(KeyInfo[++i])) ;
  415.                     i--;
  416.                int temp = strcmp(Key1->value.pCharValue,Key2->value.pCharValue);
  417.                if(temp == 0) 
  418.                  break;
  419.                else if(temp > 0)
  420.                  return 1;
  421.                else 
  422.                  return -1;
  423.                 
  424.     }
  425.     Key1 = Key1->next;
  426.     Key2 = Key2->next;    
  427.   }
  428.   return 0;
  429. }
  430. ///////////////////////////////////////////////////////////////////////////////////////////////
  431. // insert a key in the node which isn a leaf
  432. void BPTreeNode::insertKeyInLeaf(_F_FileAddr pRec,pKey_Attr pPrimKey) {
  433.   if( 0 == ItemOnNode )  // The node is empty
  434.   {
  435.     p[0] = pRec;
  436.     k[0] = pPrimKey;
  437.   }
  438. //  p[ItemOnNode + 1] = p[ItemOnNode];
  439.   for(int i=ItemOnNode-1;i>=0;i--)
  440.   {
  441.     if(compare(pPrimKey,k[i]) < 0)
  442.     {
  443.       p[i+1] = p[i];
  444.       k[i+1] = k[i];
  445.       continue;
  446.     }
  447.     else 
  448.       break;
  449.   }
  450.   p[i+1] = pRec;
  451.   k[i+1] = pPrimKey;
  452.   ItemOnNode++;
  453. }
  454. ///////////////////////////////////////////////////////////////////////////////////////////////
  455. // insert a key in the node which isn't a leaf
  456. void BPTreeNode::insertKeyNotLeaf(pKey_Attr pPrimKey,_F_FileAddr pRec) {
  457.   // the node is never empty
  458.   for(int i=ItemOnNode-1;i>=0;i--)
  459.   {
  460.     if(compare(pPrimKey,k[i]) < 0)
  461.     {
  462.       p[i+2] = p[i+1];
  463.       k[i+1] = k[i];
  464.       continue;
  465.     }
  466.     else 
  467.       break;
  468.   }
  469.   p[i+2] = pRec;
  470.   k[i+1] = pPrimKey;
  471.   ItemOnNode++;
  472. }
  473. ///////////////////////////////////////////////////////////////////////////////////////////////
  474. // delete a key in a leaf and adjust the node
  475. void BPTreeNode::deleteKeyInLeaf(pKey_Attr pPrimKey) {
  476.   int i;
  477.   for(i=0;i<ItemOnNode;i++)
  478.   {
  479.     if( compare(pPrimKey,k[i]) == 0 )
  480.       break;
  481.   }
  482.   deleteKeySpace(k[i]);  // delete the space of k[i]
  483.   // adjust the node
  484.   for(;i<ItemOnNode-1;i++)
  485.   {
  486.     p[i] = p[i+1];
  487.     k[i] = k[i+1];
  488.   }
  489.   p[ItemOnNode-1].ulFilePageID = 0;
  490.   p[ItemOnNode-1].uiOffset     = 0;
  491.   k[ItemOnNode-1]            = NULL;
  492.   ItemOnNode--;
  493. }
  494. ///////////////////////////////////////////////////////////////////////////////////////////////
  495. // delete the key in the node, and automatic adjust the node
  496. void BPTreeNode::deleteKeyNotLeaf(pKey_Attr pPrimKey) {
  497.   int i;
  498.   for(i=0;i<ItemOnNode;i++)
  499.   {
  500.     if( compare(pPrimKey,k[i]) == 0 )
  501.       break;
  502.   }
  503.   deleteKeySpace(k[i]);  // delete the space of k[i]
  504.   // adjust the node
  505.   for(;i<ItemOnNode-1;i++)
  506.   {
  507.     k[i]   = k[i+1];
  508.     p[i+1] = p[i+2];
  509.   }
  510.   k[ItemOnNode-1]          = NULL;
  511.   p[ItemOnNode].ulFilePageID = 0;
  512.   p[ItemOnNode].uiOffset     = 0;
  513.   ItemOnNode--;
  514. }
  515. ///////////////////////////////////////////////////////////////////////////////////////////////
  516. // delete the space of the first key in the node
  517. void BPTreeNode::deleteFirstKey() {
  518.     pKey_Attr head,temp;
  519.     head = temp = k[0];
  520.     for(int j=0;KeyInfo[j]!=0;j++)
  521.     {
  522.       switch(KeyInfo[j])
  523.       {
  524.         case 'i' :  // int 
  525.                     head = head->next;
  526.                     delete temp;
  527.                     temp = head;
  528.                     break;
  529.         case 'f' :  // float
  530.                     head = head->next;
  531.                     delete temp;
  532.                     temp = head;
  533.                     break;
  534.         case 'c' :  // char
  535.                     delete  [] (head->value.pCharValue);
  536.                     head = head->next;
  537.                     delete temp;
  538.                     temp = head;
  539.                     while(isdigit(KeyInfo[++j])) ;  //skip digital number
  540.                     j--;
  541.                     break;
  542.       }
  543.     }
  544.     for(int i=0;i<ItemOnNode-1;i++)
  545.     {
  546.       p[i] = p[i+1];
  547.       k[i] = k[i+1];
  548.     }
  549.     p[ItemOnNode-1] = p[ItemOnNode];
  550.     p[ItemOnNode].ulFilePageID = 0;
  551.     p[ItemOnNode].uiOffset     = 0;
  552.     k[ItemOnNode - 1]        = NULL;
  553.     ItemOnNode--;
  554. }
  555. ///////////////////////////////////////////////////////////////////////////////////////////////
  556. // delete the space of the key
  557. void BPTreeNode::deleteKeySpace(pKey_Attr Key) {
  558.   pKey_Attr head,temp;
  559.   head = temp = Key;
  560.   for(int j=0;KeyInfo[j]!=0;j++)
  561.   {
  562.     switch(KeyInfo[j])
  563.     {
  564.       case 'i' :  // int 
  565.                   head = head->next;
  566.                   delete temp;
  567.                   temp = head;
  568.                   break;
  569.       case 'f' :  // float
  570.                   head = head->next;
  571.                   delete temp;
  572.                   temp = head;
  573.                   break;
  574.       case 'c' :  // char
  575.                   delete  [] (head->value.pCharValue);
  576.                   head = head->next;
  577.                   delete temp;
  578.                   temp = head;
  579.                   while(isdigit(KeyInfo[++j])) ;  //skip digital number
  580.                   j--;
  581.                   break;
  582.     }
  583.   }
  584. }
  585. ///////////////////////////////////////////////////////////////////////////////////////////////
  586. // create a key equal to Key1,and automatic open a new space 
  587. pKey_Attr BPTreeNode::createKey(pKey_Attr Key1) {
  588.   pKey_Attr Key2,temp;
  589.   for(int j=0; KeyInfo[j]!='';j++)
  590.   {
  591.     if(j == 0)    // the first node
  592.       Key2 = temp = new Key_Attr;
  593.     else
  594.     {
  595.       temp->next = new Key_Attr;
  596.       temp       = temp->next;
  597.     }
  598.     switch(KeyInfo[j])
  599.     {
  600.       case 'i'  :  // int value  
  601.                    temp->value.IntValue = Key1->value.IntValue;
  602.                    temp->next           = NULL;
  603.                    break;
  604.       case 'f'  :  // float value 
  605.                    temp->value.FloatValue = Key1->value.FloatValue;
  606.                    temp->next           = NULL;
  607.                    break;
  608.       case 'c'  :  // string
  609.                    int num = 0;
  610.                    for( j=j+1; isdigit(KeyInfo[j]); j++)
  611.                    {
  612.                      num = num * 10 + KeyInfo[j] - '0';
  613.                    }
  614.                    j--;        // move the index back
  615.                    num++;      // for '' which is the end of a string
  616.                    char* pCharValue = new char [num];
  617.                    char* str = Key1->value.pCharValue;
  618.                    strcpy(pCharValue,str);
  619.                    temp->value.pCharValue = pCharValue;
  620.                    temp->next             = NULL;
  621.                    break;                  
  622.     }
  623.     Key1 = Key1->next;  // move to the next node
  624.   }  //KeyInfo[i] = ''
  625.   return Key2;
  626. }
  627. ///////////////////////////////////////////////////////////////////////////////////////////////
  628. bool BPTreeNode::isNotEnoughPoints() {
  629.   int n = MaxItem + 1;  
  630.   if( 0 == IsLeaf )  // it isn't a leaf
  631.   {
  632.     int m;
  633.     if( !(n%2) )
  634.       m = n/2 ;  // n = NodeL.MaxItem + 1
  635.     else 
  636.       m = n/2 + 1;
  637.     if( (ItemOnNode + 1) < m)  // not enough points ,ItemOnNode+1 is the number of points
  638.       return true;
  639.     else 
  640.       return false;
  641.   }
  642.   else // it is a leaf
  643.   {
  644.     int m;
  645.     if( ! ((n-1)%2) )
  646.       m = (n-1)/2 ;  // n = NodeL.MaxItem + 1
  647.     else 
  648.       m = (n-1)/2 + 1;
  649.     if( ItemOnNode < m )  // not enough points
  650.       return true;
  651.     else 
  652.       return false;
  653.   }
  654. }
  655. ////////////////////////////////////////////////////////////////////////////////////////////////////
  656. /*=========================================================================
  657. =========                 definition for BPTree               =============
  658. =========================================================================*/
  659. ////////////////////////////////////////////////////////////////////////////////////////////////////
  660. //constructor
  661. BPTree::BPTree() {
  662. _F_FileAddr temp;
  663. temp.ulFilePageID = 0;
  664. temp.uiOffset     = 0;
  665. for(int i=0; i<DEPTH; i++)
  666. SearchPath[i] = temp;
  667. }
  668. //destructor
  669. BPTree::~BPTree() {
  670. }
  671. ////////////////////////////////////////////////////////////////////////////////////////////////////
  672. void BPTree::setPath() {
  673. char address[256];
  674. strcpy(address, CurLocation);
  675. strcat(address, CurRelationName);
  676. strcat(address, ".idx");
  677. _M_File test = Buffer[address]; 
  678. }
  679. ////////////////////////////////////////////////////////////////////////////////////////////////////
  680. void BPTree::create(char *KeyStr) {
  681. setPath();
  682. BPTree_Index idx;
  683. idx.createHead(KeyStr);
  684. idx.writeHeadToFile();
  685. BPTreeNode root;
  686. root.IsLeaf = 1;
  687. root.writeNodeToFile(idx.getRoot());
  688. }
  689. ////////////////////////////////////////////////////////////////////////////////////////////////////
  690. void BPTree::createNewRoot(_F_FileAddr p0, pKey_Attr pPrimKey, _F_FileAddr p1) {
  691. _F_FileAddr Newroot;
  692. Newroot = createNodeInFile();
  693. BPTree_Index idx;
  694. idx.readHeadFromFile();
  695. idx.IdxHead.root = Newroot;
  696. idx.writeHeadToFile();
  697. BPTreeNode Root;
  698. Root.IsLeaf = 0;
  699. Root.ItemOnNode = 1;
  700. Root.p[0] = p0;
  701. Root.p[1] = p1;
  702. Root.k[0] = pPrimKey;
  703. Root.writeNodeToFile(Newroot);
  704. }
  705. ////////////////////////////////////////////////////////////////////////////////////////////////////
  706. void BPTree::grantRoot(_F_FileAddr pfa) {
  707. BPTree_Index idx;
  708. idx.readHeadFromFile();
  709. idx.IdxHead.root = pfa;
  710. idx.writeHeadToFile();
  711. }
  712. ///////////////////////////////////////////////////////////////////////////////////////////////////
  713. void BPTree::deleteNodeInFile(_F_FileAddr pfa) {
  714. BPTree_Index idx;
  715. idx.readHeadFromFile();
  716. //make the first empty block point to the new delete block
  717. if(idx.IdxHead.FirstEmptyBlock.ulFilePageID == 0) {
  718. idx.IdxHead.FirstEmptyBlock = pfa;
  719. idx.IdxHead.LastEmptyBlock  = pfa;
  720. }
  721. else {
  722.     // make the last empty block point to the new delete block
  723.     BPTreeNode NextNode;
  724. NextNode.readNodeFromFile(idx.IdxHead.LastEmptyBlock);
  725.     NextNode.Next_Empty_Block = pfa;
  726.     NextNode.writeNodeToFile(idx.IdxHead.LastEmptyBlock);
  727.     // change the index head 
  728.     idx.IdxHead.LastEmptyBlock = pfa;
  729. }
  730. idx.writeHeadToFile();
  731. }
  732. ///////////////////////////////////////////////////////////////////////////////////////////////////
  733. //--
  734. bool BPTree::search(pKey_Attr pPrimKey, pKey_Location pKeyLoca) {
  735. setPath();
  736. BPTree_Index idx;
  737. idx.readHeadFromFile();
  738. _F_FileAddr pfa = idx.getRoot();
  739. BPTreeNode Node;
  740. for(int level=0; level<DEPTH; level++) {
  741. Node.readNodeFromFile(pfa);
  742. SearchPath[level] = pfa;
  743. //not leaf
  744. if(Node.IsLeaf == 0) {
  745. for(int i=0; i<=Node.ItemOnNode; i++) {
  746. if(i == Node.ItemOnNode) {
  747. pfa = Node.p[i];
  748. break;
  749. }
  750. else if(Node.compare(pPrimKey, Node.k[i]) < 0) {
  751. pfa = Node.p[i];
  752. break;
  753. }
  754. else if(Node.compare(pPrimKey,Node.k[i]) >= 0)
  755. continue;
  756. }
  757. }
  758. else {
  759. //is leaf
  760. for(int j=0; j<=Node.ItemOnNode; j++) {
  761. if(j == Node.ItemOnNode) {
  762. pKeyLoca->ptr = pfa;
  763. pKeyLoca->offset = Node.MaxItem;
  764. return false;
  765. }
  766. else if(Node.compare(pPrimKey, Node.k[j]) == 0) {
  767. pKeyLoca->ptr = pfa;
  768. pKeyLoca->offset = j;
  769. return true;
  770. }
  771. else if( Node.compare(pPrimKey,Node.k[j]) > 0 )  // pPrimKey > k[i]
  772. continue;
  773. else {
  774. pKeyLoca->ptr    = pfa;
  775. pKeyLoca->offset = j;
  776. return false;
  777. }
  778. }
  779. }
  780. }
  781. throw 1028;
  782. }
  783. ///////////////////////////////////////////////////////////////////////////////////////////////////
  784. //--
  785. bool BPTree::isRoot(_F_FileAddr pfa) {
  786. return SearchPath[0] == pfa;
  787. }
  788. ///////////////////////////////////////////////////////////////////////////////////////////////////
  789. //--
  790. bool BPTree::isEmpty() {
  791. Key_Location KeyLoca;
  792. // cout<<"begin isEmpty()"<<endl;//=======//
  793. KeyLoca = getStart();
  794. BPTreeNode FirstNode;
  795. FirstNode.readNodeFromFile(KeyLoca.ptr);
  796. // cout<<"end isEmpty()"<<endl;  //=====//
  797. if(FirstNode.ItemOnNode == 0)
  798. return true;
  799. return false;
  800. }
  801. ///////////////////////////////////////////////////////////////////////////////////////////////////
  802. //--
  803. Key_Location BPTree::moveToNextKey(Key_Location KeyLoca) {
  804. Key_Location temp;
  805. BPTreeNode node; 
  806. node.readNodeFromFile(KeyLoca.ptr);
  807. if( node.MaxItem == KeyLoca.offset ) {
  808. if(node.p[node.MaxItem].ulFilePageID == 0)
  809. temp.ptr.ulFilePageID = 0;
  810. else {
  811. // get the address of the first key in the next node 
  812. BPTreeNode NextNode;
  813. NextNode.readNodeFromFile(node.p[node.MaxItem]);
  814. temp.ptr = node.p[node.MaxItem];
  815. temp.offset = 0;
  816. }
  817. return temp;
  818. }
  819. int i = KeyLoca.offset + 1;
  820. // the next key is empty or full
  821. if( 0 == node.p[i].ulFilePageID || node.MaxItem == i) {
  822. i = node.MaxItem;  // the last p[MaxItem]
  823. if( 0 == node.p[i].ulFilePageID ) 
  824. temp.ptr.ulFilePageID = 0;
  825. else {
  826. BPTreeNode NextNode;
  827. NextNode.readNodeFromFile(node.p[i]);
  828. temp.ptr = node.p[i];
  829. temp.offset = 0;
  830. }
  831. }
  832. else {
  833. // the address of the next key in the current node 
  834. temp.ptr = KeyLoca.ptr;
  835. temp.offset = KeyLoca.offset + 1;
  836. }
  837. return temp;
  838. }
  839. ///////////////////////////////////////////////////////////////////////////////////////////////////
  840. //this method returns the address of the first key in the leftest leaf node
  841. //--
  842. Key_Location BPTree::getStart() {
  843. BPTree_Index idx;
  844. idx.readHeadFromFile();
  845. _F_FileAddr ptr = idx.getRoot();
  846.   
  847.     for( ; ; ) {
  848. BPTreeNode Node;
  849. Node.readNodeFromFile(ptr);
  850. if( 1 == Node.IsLeaf ) {
  851. Key_Location temp;
  852. temp.ptr = ptr;
  853. temp.offset = 0;
  854. return temp;
  855. }
  856. else
  857. ptr = Node.p[0];
  858. }
  859. }
  860. ///////////////////////////////////////////////////////////////////////////////////////////////////
  861. //--
  862. _F_FileAddr BPTree::getParent(_F_FileAddr ptr) {
  863. for(int i=0; SearchPath[i].ulFilePageID != 0; i++) {
  864. if(SearchPath[i] == ptr)
  865. return SearchPath[i-1];  
  866. }
  867. throw 1022;
  868. }
  869. ///////////////////////////////////////////////////////////////////////////////////////////////////
  870. //this method returns the address specified by Key_Location
  871. //--
  872. _F_FileAddr BPTree::getCurRecAddr(Key_Location KeyLoca) {
  873. BPTreeNode node;
  874. node.readNodeFromFile(KeyLoca.ptr);
  875. return node.p[KeyLoca.offset];
  876. }
  877. ///////////////////////////////////////////////////////////////////////////////////////////////////
  878. //--
  879. _F_FileAddr BPTree::createNodeInFile() {
  880. BPTree_Index idx;
  881. idx.readHeadFromFile();
  882. //the index file has no empty block
  883. if( 0 == idx.IdxHead.FirstEmptyBlock.ulFilePageID ) {
  884. // firstly,we should check whether the block overflow the current page
  885. // If so,use the next page 
  886. void* CheckOverflow = (void*) new char[BTreeNodeSize];
  887. _F_FileAddr Next = MemWrite(CheckOverflow, BTreeNodeSize, &idx.IdxHead.FirstNewBlock);
  888. _F_FileAddr temp = idx.IdxHead.FirstNewBlock;
  889. idx.IdxHead.FirstNewBlock = Next;
  890. idx.writeHeadToFile();
  891. return temp;
  892. }
  893. else {
  894. int flag = 0;  
  895. if(idx.IdxHead.FirstEmptyBlock ==  idx.IdxHead.LastEmptyBlock)
  896. flag = 1;
  897. _F_FileAddr temp = idx.IdxHead.FirstEmptyBlock;
  898. if( 1 == flag) { 
  899. //there is just one empty block
  900. idx.IdxHead.FirstEmptyBlock.ulFilePageID = 0;
  901. idx.IdxHead.FirstEmptyBlock.uiOffset     = 0;
  902. idx.IdxHead.LastEmptyBlock.ulFilePageID  = 0;
  903. idx.IdxHead.LastEmptyBlock.uiOffset      = 0;
  904. }
  905. else {
  906. // change FisrtEmptyBlock point to the next block
  907. BPTreeNode NextNode;
  908. NextNode.readNodeFromFile(temp);
  909. idx.IdxHead.FirstEmptyBlock = NextNode.Next_Empty_Block;
  910. }
  911. idx.writeHeadToFile();
  912. return temp;
  913. }
  914. }
  915. ///////////////////////////////////////////////////////////////////////////////////////////////////
  916. //this method returns the address of the last key in the rightest node
  917. //--
  918. Key_Location BPTree::getEnd() {
  919. BPTree_Index idx;
  920. idx.readHeadFromFile();
  921. _F_FileAddr ptr = idx.getRoot();
  922. for( ; ; ) {
  923. BPTreeNode Node;
  924. Node.readNodeFromFile(ptr);
  925. if( 1 == Node.IsLeaf ) {
  926. Key_Location temp;
  927. temp.ptr = ptr;
  928. temp.offset = Node.ItemOnNode - 1;
  929. return temp;  // return the first address of the first Key in the first node
  930. }
  931. else
  932. ptr = Node.p[Node.ItemOnNode];
  933. }
  934. }
  935. ///////////////////////////////////////////////////////////////////////////////////////////////////
  936. //--
  937. void BPTree::insert(pKey_Attr pPrimKey, _F_FileAddr pRec) {
  938. setPath();
  939. Key_Location KeyLoca;
  940. if(search(pPrimKey, &KeyLoca))
  941. throw 1024;
  942. else 
  943. insert_entry(KeyLoca.ptr, pPrimKey, pRec);
  944. }
  945. ///////////////////////////////////////////////////////////////////////////////////////////////////
  946. //--
  947. void BPTree::insert_entry(_F_FileAddr L, pKey_Attr pPrimKey, _F_FileAddr pRec) {
  948. BPTreeNode NodeL;
  949. NodeL.readNodeFromFile(L);
  950. //if L has less than n-1 key values
  951. if(NodeL.ItemOnNode < NodeL.MaxItem) {
  952. if(NodeL.IsLeaf ==1)
  953. NodeL.insertKeyInLeaf(pRec, pPrimKey);
  954. else
  955. NodeL.insertKeyNotLeaf(pPrimKey, pRec);
  956. }
  957. else {
  958. //create a new node
  959. _F_FileAddr L_ = createNodeInFile();
  960. BPTreeNode NodeL_;
  961. pKey_Attr pPrimKey_;
  962. int n = NodeL.MaxItem + 1;
  963. if(NodeL.IsLeaf ==1) {
  964. NodeL_.IsLeaf = 1;
  965. int m;
  966. if( !(n%2) )
  967. m = n/2 ;
  968. else 
  969. m = n/2 + 1;
  970. //p[0]k[0]...k[m-1]p[m] | k[m]...
  971. // pPrimKey < k[m-1]
  972. if( NodeL.compare(NodeL.k[m-1], pPrimKey) > 0) { 
  973. m--;                                  
  974. pPrimKey_ = NodeL.createKey(NodeL.k[m]);
  975. }
  976. // k[m] > pPrimKey >= k[m-1]
  977. else if( (m == n - 1) || ( NodeL.compare(NodeL.k[m], pPrimKey) > 0 ) ) 
  978. pPrimKey_ = NodeL.createKey(pPrimKey);
  979. else
  980. // pPrimKey > k[m]
  981. pPrimKey_ = NodeL.createKey(NodeL.k[m]);
  982. //copy p[m]....to L_
  983. for(int i=m; i<NodeL.MaxItem; i++) {
  984. NodeL_.p[i-m] = NodeL.p[i];
  985. NodeL_.k[i-m] = NodeL.k[i];
  986. //erase
  987. NodeL.k[i] = NULL;
  988. NodeL.p[i].ulFilePageID = 0;
  989. NodeL.p[i].uiOffset     = 0;
  990. NodeL_.ItemOnNode++;
  991. NodeL.ItemOnNode--;
  992. }
  993. if(NodeL.compare(pPrimKey, pPrimKey_) < 0)
  994. NodeL.insertKeyInLeaf(pRec,pPrimKey);
  995. else
  996. NodeL_.insertKeyInLeaf(pRec,pPrimKey);
  997. }
  998. else { //NodeL is not a leaf
  999. NodeL_.IsLeaf = 0;
  1000. int m;
  1001. if( !(n%2) )
  1002. m = n/2 ;
  1003. else 
  1004. m = n/2 + 1;
  1005. m = NodeL.MaxItem - m;
  1006. //p[0],k[0]....k[m]p[m+1] | k[m+1]...
  1007. //pPrimKey > k[m+1]
  1008. if( NodeL.compare(pPrimKey, NodeL.k[m+1]) > 0 ) {
  1009. m++;
  1010. pPrimKey_ = NodeL.createKey(NodeL.k[m]);
  1011. }
  1012. // k[m] < pPrimKey <= k[m+1]
  1013. else if( NodeL.compare(pPrimKey, NodeL.k[m]) > 0 ) {
  1014. m++;
  1015. pPrimKey_ = NodeL.createKey(pPrimKey);
  1016. }
  1017. // pPrimKey <= k[m]
  1018. else {
  1019. pPrimKey_ = NodeL.createKey(NodeL.k[m]);
  1020. }
  1021. // move and delete
  1022. NodeL_.p[0].ulFilePageID = 0;
  1023. NodeL_.p[0].uiOffset     = 0;  
  1024. NodeL_.k[0] = NodeL.k[m];
  1025. NodeL.k[m] = NULL;
  1026. NodeL_.ItemOnNode++;
  1027. NodeL.ItemOnNode--;
  1028. for(int i=m+1; i<NodeL.MaxItem; i++) {
  1029. NodeL_.p[i-m] = NodeL.p[i];
  1030. NodeL_.k[i-m] = NodeL.k[i];
  1031. //erase
  1032. NodeL.k[i] = NULL;
  1033. NodeL.p[i].ulFilePageID = 0;
  1034. NodeL.p[i].uiOffset     = 0;
  1035. NodeL_.ItemOnNode++;
  1036. NodeL.ItemOnNode--;
  1037. }
  1038. NodeL_.p[i-m] = NodeL.p[i];
  1039. NodeL.p[i].ulFilePageID = 0;
  1040. NodeL.p[i].uiOffset     = 0;
  1041. if( NodeL.compare(pPrimKey, pPrimKey_) < 0 )
  1042. NodeL.insertKeyNotLeaf(pPrimKey, pRec);
  1043. else 
  1044. NodeL_.insertKeyNotLeaf(pPrimKey,pRec);
  1045. NodeL_.deleteFirstKey();
  1046. }
  1047. if( !isRoot(L) )
  1048. insert_entry(getParent(L), pPrimKey_, L_);
  1049. else
  1050. createNewRoot(L, pPrimKey_, L_);  
  1051. if(NodeL.IsLeaf == 1) {
  1052. NodeL_.p[NodeL.MaxItem] = NodeL.p[NodeL.MaxItem];
  1053. NodeL.p[NodeL.MaxItem]  = L_;
  1054. }
  1055. NodeL_.writeNodeToFile(L_);
  1056. }
  1057. NodeL.writeNodeToFile(L);
  1058. }
  1059. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  1060. bool BPTree::canCoalesce(BPTreeNode* pNode, BPTreeNode* pNode_) {
  1061. if(pNode->IsLeaf == 1)
  1062. return (pNode->ItemOnNode + pNode_->ItemOnNode <= pNode->MaxItem);
  1063. else
  1064. return (pNode->ItemOnNode + pNode_->ItemOnNode < pNode->MaxItem);   
  1065. }
  1066. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  1067. void BPTree::coalesce(BPTreeNode* pNodeL, BPTreeNode* pNodeL_, pKey_Attr pPrimKey_, bool IsLLeftOfL_) {
  1068. if( 0 == pNodeL->IsLeaf ) {
  1069. if(IsLLeftOfL_) {
  1070. //move right
  1071. int j = pNodeL->ItemOnNode + 1;
  1072. pNodeL_->p[pNodeL_->ItemOnNode + j] = pNodeL_->p[pNodeL_->ItemOnNode];
  1073. for(int i=pNodeL_->ItemOnNode-1; i>=0; i--) {
  1074. pNodeL_->k[i + j] = pNodeL_->k[i];
  1075. pNodeL_->p[i + j] = pNodeL_->p[i];
  1076. }
  1077. //assign V' to the pNodeL_
  1078. pNodeL_->k[j-1] = pPrimKey_;
  1079. pNodeL_->p[j-1] = pNodeL->p[pNodeL->ItemOnNode];
  1080. // move all elements in pNodeL to pNodeL_
  1081. for(i=0; i<pNodeL->ItemOnNode; i++) {
  1082. pNodeL_->p[i] = pNodeL->p[i];
  1083. pNodeL_->k[i] = pNodeL->k[i];
  1084. }
  1085. // set ItemOnNode in pNodeL_
  1086. pNodeL_->ItemOnNode = pNodeL_->ItemOnNode + pNodeL->ItemOnNode + 1;
  1087. pNodeL->initialize();
  1088. }
  1089. else { //L is right of L_
  1090. int j = pNodeL_->ItemOnNode + 1;
  1091. pNodeL_->k[pNodeL_->ItemOnNode] = pPrimKey_; 
  1092. for(int i=0;i<pNodeL->ItemOnNode;i++) {
  1093. pNodeL_->p[i+j] = pNodeL->p[i];
  1094. pNodeL_->k[i+j] = pNodeL->k[i];
  1095. }
  1096. pNodeL_->p[i+j] = pNodeL->p[i];
  1097. pNodeL_->ItemOnNode = pNodeL_->ItemOnNode + pNodeL->ItemOnNode + 1;
  1098. pNodeL->initialize();
  1099. }
  1100. }
  1101. else { // (pNodeL->IsLeaf == 1)
  1102. if(IsLLeftOfL_) {
  1103. int j = pNodeL->ItemOnNode;
  1104. for(int i=0; i<pNodeL_->ItemOnNode; i++) {
  1105. pNodeL->p[i+j] = pNodeL_->p[i];
  1106. pNodeL->k[i+j] = pNodeL_->k[i];
  1107. }
  1108. pNodeL->ItemOnNode += pNodeL_->ItemOnNode;
  1109. pNodeL->p[pNodeL->MaxItem] = pNodeL_->p[pNodeL_->MaxItem];
  1110. pNodeL_->initialize();
  1111. }
  1112. else { // L is right of L_
  1113. int j = pNodeL_->ItemOnNode;
  1114. for(int i=0; i<pNodeL->ItemOnNode; i++) {
  1115. pNodeL_->p[i+j] = pNodeL->p[i];
  1116. pNodeL_->k[i+j] = pNodeL->k[i];
  1117. }
  1118. pNodeL_->ItemOnNode += pNodeL->ItemOnNode;
  1119. pNodeL_->p[pNodeL_->MaxItem] = pNodeL->p[pNodeL->MaxItem];
  1120. pNodeL->initialize();
  1121. }
  1122. }
  1123. }
  1124. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  1125. //this method swaps the pointers to node L and L_
  1126. void BPTree::swapVariables(_F_FileAddr L, _F_FileAddr L_) {
  1127. BPTreeNode ParentNode;
  1128. ParentNode.readNodeFromFile(getParent(L));
  1129. int m,n;
  1130. // find the indexes of L and L_ 
  1131. for(int i=0; i <= ParentNode.ItemOnNode; i++) {
  1132. if( ParentNode.p[i] == L )
  1133. m = i;
  1134. if( ParentNode.p[i] == L_ )
  1135. n = i;
  1136. }
  1137. // swap
  1138. _F_FileAddr temp;
  1139. temp = ParentNode.p[m];
  1140. ParentNode.p[m] = ParentNode.p[n];
  1141. ParentNode.p[n] = temp;
  1142. ParentNode.writeNodeToFile(getParent(L));
  1143. }
  1144. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  1145. //this method makes pL_ and ppPrimKey points the infomation that is a neighbour of L
  1146. // and pIsLLeftOnL_ indicate whether L is left neighbour of L_ or not
  1147. void BPTree::setNb(_F_FileAddr L, _F_FileAddr* pL_, pKey_Attr* ppPrimKey_, bool* pIsLLeftOfL_) {
  1148. BPTreeNode ParentNode;
  1149. ParentNode.readNodeFromFile(getParent(L));
  1150. for(int i=0; i<=ParentNode.ItemOnNode; i++) {
  1151. if( ParentNode.p[i] == L )
  1152. break;
  1153. }
  1154. if( 0 == i ) { // L is the leftest son of the parent node
  1155. (*pL_)          = ParentNode.p[1];
  1156. (*ppPrimKey_)   = ParentNode.createKey(ParentNode.k[0]);
  1157. (*pIsLLeftOfL_) = true;  // L is on the left of L_
  1158. }
  1159. else {
  1160. (*pL_)          = ParentNode.p[i-1];
  1161. (*ppPrimKey_)   = ParentNode.createKey(ParentNode.k[i-1]);
  1162. (*pIsLLeftOfL_) = false;
  1163. }
  1164. }
  1165. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  1166. //this method replaces the key equal to Key_ with Key in the node pointed by ptr  
  1167. //--
  1168. void BPTree::replaceKey(_F_FileAddr ptr, pKey_Attr Key_, pKey_Attr Key) {
  1169. BPTreeNode Node;
  1170. Node.readNodeFromFile(ptr);
  1171. for(int i=0; i<Node.ItemOnNode; i++) {
  1172. if( 0 == Node.compare(Node.k[i], Key_) )
  1173. break;
  1174. }
  1175. Node.deleteKeySpace(Node.k[i]);
  1176. Node.k[i] = Key;
  1177. Node.writeNodeToFile(ptr);
  1178. }
  1179. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  1180. void BPTree::reDistribute(BPTreeNode* pNodeL, BPTreeNode* pNodeL_, pKey_Attr pPrimKey_, 
  1181.   bool IsLLeftOfL_, _F_FileAddr L) {
  1182. int m;
  1183. if( !IsLLeftOfL_ ) {
  1184. if( !pNodeL->IsLeaf ) {
  1185. m = pNodeL_->ItemOnNode;
  1186. //  move all k[i] and p[i] in L to right by one
  1187. pNodeL->p[pNodeL->ItemOnNode+1] = pNodeL->p[pNodeL->ItemOnNode];
  1188. for(int i=pNodeL->ItemOnNode-1; i>=0; i--) {
  1189. pNodeL->k[i+1] = pNodeL->k[i];
  1190. pNodeL->p[i+1] = pNodeL->p[i];
  1191. }
  1192. pNodeL->k[0] = pPrimKey_;
  1193. pNodeL->p[0] = pNodeL_->p[m];
  1194. pNodeL->ItemOnNode++;
  1195. //replace K_ in parent of L by k[m-1]
  1196. replaceKey(getParent(L), pPrimKey_, pNodeL_->k[m-1]);
  1197. //remove k[m-1] and p[m] from L_
  1198. pNodeL_->k[m-1] = NULL;
  1199. pNodeL_->p[m].ulFilePageID = 0;
  1200. pNodeL_->p[m].uiOffset     = 0;
  1201. pNodeL_->ItemOnNode--;
  1202. }
  1203. else { //(pNodeL->IsLeaf == 1)
  1204. m = pNodeL_->ItemOnNode - 1;
  1205. //  move all k[i] and p[i] in L to right by one
  1206. for(int i=pNodeL->ItemOnNode-1; i>=0; i--) {
  1207. pNodeL->k[i+1] = pNodeL->k[i];
  1208. pNodeL->p[i+1] = pNodeL->p[i];
  1209. }
  1210. pNodeL->k[0] = pNodeL_->k[m];
  1211. pNodeL->p[0] = pNodeL_->p[m];
  1212. pNodeL->ItemOnNode++;
  1213. //replace K_ in parent of L by k[m]
  1214. pKey_Attr temp = pNodeL_->createKey(pNodeL_->k[m]);
  1215. replaceKey(getParent(L), pPrimKey_, temp);
  1216. pNodeL->deleteKeySpace(pPrimKey_);
  1217. //remove p[m] and k[m] from L_ 
  1218. pNodeL_->k[m] = NULL;
  1219. pNodeL_->p[m].ulFilePageID = 0;
  1220. pNodeL_->p[m].uiOffset     = 0;
  1221. pNodeL_->ItemOnNode--;
  1222. }
  1223. }
  1224. else { //(IsLLeftOfL_)
  1225. if( !pNodeL->IsLeaf ) {
  1226. pNodeL->k[pNodeL->ItemOnNode] = pPrimKey_;
  1227. pNodeL->p[pNodeL->ItemOnNode + 1] = pNodeL_->p[0];
  1228. pNodeL->ItemOnNode++;
  1229. replaceKey(getParent(L), pPrimKey_, pNodeL_->k[0]);
  1230. // move pNodeL_ to the left by one
  1231. for(int i=1; i<pNodeL_->ItemOnNode; i++) {
  1232. pNodeL_->k[i-1] = pNodeL_->k[i];
  1233. pNodeL_->p[i-1] = pNodeL_->p[i];
  1234. }
  1235. pNodeL_->p[i-1] = pNodeL_->p[i];
  1236. pNodeL_->k[pNodeL_->ItemOnNode-1] = NULL;
  1237. pNodeL_->p[pNodeL_->ItemOnNode].ulFilePageID = 0;
  1238. pNodeL_->p[pNodeL_->ItemOnNode].uiOffset     = 0;
  1239. pNodeL_->ItemOnNode--;
  1240. }
  1241. else { //(pNodeL->IsLeaf)
  1242. pNodeL->k[pNodeL->ItemOnNode] = pNodeL_->k[0];
  1243. pNodeL->p[pNodeL->ItemOnNode] = pNodeL_->p[0];
  1244. pNodeL->ItemOnNode++;
  1245. for(int i=1; i<pNodeL_->ItemOnNode; i++) {
  1246. pNodeL_->k[i-1] = pNodeL_->k[i];
  1247. pNodeL_->p[i-1] = pNodeL_->p[i];
  1248. }
  1249. pNodeL_->k[pNodeL_->ItemOnNode-1] = NULL;
  1250. pNodeL_->p[pNodeL_->ItemOnNode-1].ulFilePageID = 0;
  1251. pNodeL_->p[pNodeL_->ItemOnNode-1].uiOffset     = 0;
  1252. pNodeL_->ItemOnNode--;
  1253. pKey_Attr temp = pNodeL_->createKey(pNodeL_->k[0]); 
  1254. replaceKey(getParent(L), pPrimKey_, temp);
  1255. pNodeL->deleteKeySpace(pPrimKey_);
  1256. }
  1257. }
  1258. }
  1259. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  1260. void BPTree::myDelete(pKey_Attr pPrimKey, _F_FileAddr& pRec) {
  1261. setPath();
  1262. Key_Location KeyLoca;
  1263. if(search(pPrimKey, &KeyLoca)) {
  1264. pRec = getCurRecAddr(KeyLoca);
  1265. delete_entry(KeyLoca.ptr, pPrimKey, pRec);    
  1266. }
  1267. else
  1268. throw 1023;
  1269. }
  1270. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  1271. void BPTree::delete_entry(_F_FileAddr L, pKey_Attr pPrimKey, _F_FileAddr pRec) {
  1272. BPTreeNode NodeL;
  1273. NodeL.readNodeFromFile(L);
  1274. // delete the (V,P) entry
  1275. if( 1 == NodeL.IsLeaf )
  1276. NodeL.deleteKeyInLeaf(pPrimKey);
  1277. else 
  1278. NodeL.deleteKeyNotLeaf(pPrimKey);
  1279. // L is root and has only one son and not a leaf
  1280. if( isRoot(L) && ( 0 == NodeL.ItemOnNode ) && (0 == NodeL.IsLeaf) )  {
  1281. grantRoot(NodeL.p[0]); // grant root to the son
  1282. deleteNodeInFile(L);   // delete node 
  1283. }
  1284. else 
  1285. if( !isRoot(L) && NodeL.isNotEnoughPoints() )  {// isn't root and not enough points
  1286. //set L_ neighbour of L
  1287. bool IsLLeftOfL_;
  1288. _F_FileAddr L_;
  1289. pKey_Attr pPrimKey_;
  1290. setNb(L, &L_, &pPrimKey_, &IsLLeftOfL_);
  1291.     
  1292. BPTreeNode NodeL_;
  1293. NodeL_.readNodeFromFile(L_);
  1294. if( canCoalesce(&NodeL, &NodeL_)) {
  1295. if(IsLLeftOfL_) 
  1296. swapVariables(L,L_); 
  1297. coalesce(&NodeL, &NodeL_, pPrimKey_, IsLLeftOfL_);
  1298. if( NodeL.IsLeaf && IsLLeftOfL_ ) // differe from book 
  1299. swapVariables(L,L_);       
  1300. delete_entry(getParent(L), pPrimKey_, L);
  1301. if( NodeL.IsLeaf && IsLLeftOfL_ )  // L is a leaf and L < L_. Different from the book
  1302. deleteNodeInFile(L_);  // delete the node pointed by L_
  1303. else
  1304. deleteNodeInFile(L);   // delete the node pointed by L
  1305. }
  1306. else 
  1307.   reDistribute(&NodeL, &NodeL_, pPrimKey_, IsLLeftOfL_, L);
  1308. NodeL_.writeNodeToFile(L_);
  1309. }
  1310. NodeL.writeNodeToFile(L);  // if though the node is delete
  1311. }
  1312. ///////////////////////////////////////////////////////////////////////////////////////////////////////////