/************************************************
  * No Change    
  * RETURN:
  *    success    - successfully created the index list header
  *    failure    - it did not create the index list header    
  ***********************************************************/  
  const int  IndexList::updateLastPtr(const int lastCount)  
  { 
       int rc;
       if (m_curBlock.state == BLK_INIT)
            readCurBlk();    
       if (m_useNarray)
       {
          rc = setCurBlkNextPtr(m_nextLbid, lastCount);
          rc = writeCurBlk();            
       }
       else
       {
          ((IdxEmptyListEntry*)&m_lastIdxRidListPtr)->fbo  = m_nextLbid;
          ((IdxEmptyListEntry*)&m_lastIdxRidListPtr)->sbid = 0;
          ((IdxEmptyListEntry*)&m_lastIdxRidListPtr)->entry= 0;
          m_lastIdxRidListPtr.type= LIST_BLOCK_TYPE;
          m_lastIdxRidListPtr.spare=0x0;
          m_lastIdxRidListPtr.count = lastCount; 
                       
          setSubBlockEntry( m_curBlock.data, m_sbid, 
                            LIST_BLOCK_LLP_POS, LIST_ENTRY_WIDTH , 
                            &m_lastIdxRidListPtr );
          m_curBlock.state = BLK_WRITE;
          rc = writeCurBlk();
       } 
       return rc;  
  }            
 /************************************************
  * No Change    
  * RETURN:
  *    success    - successfully created the index list header
  *    failure    - it did not create the index list header    
  ***********************************************************/ 
  const int IndexList::insertRid(const RID& newRid, int& pos)
  {
     int rc = NO_ERROR;     
     IdxRidListEntry idxRidListEntry;  
     
     if (m_curType == LIST_BLOCK_TYPE)
     {
           m_sbid = 0;
           m_entry = 0;
     }
     memset(&idxRidListEntry, 0, LIST_ENTRY_WIDTH)  ;
     
     idxRidListEntry.type  =LIST_RID_TYPE;
     idxRidListEntry.spare =0;
     //cout << "line 910:newRid->" << newRid << endl;
     
     idxRidListEntry.rid   =newRid;  
     if (m_lbid != m_hdrLbid)  
     {
        rc = readCurBlk();     
        setSubBlockEntry( m_curBlock.data, m_sbid, pos, LIST_ENTRY_WIDTH, 
                          &idxRidListEntry );
        m_curBlock.state = BLK_WRITE;
        
     }
     else
     {
        setSubBlockEntry( m_hdrBlock.data, m_sbid, pos, LIST_ENTRY_WIDTH, 
                          &idxRidListEntry ); 
        m_hdrBlock.state = BLK_WRITE;
     }
     return rc;
  } 
 /***********************************************************
  * DESCRIPTION:
  * RETURN:
  *    success NO_ERROR
  *    fail    
  ***********************************************************/  
  const int IndexList::moveRidsToNewSub(FILE* pFile, const RID& oldRid, 
                                        const RID& newRid,
                                        IdxEmptyListEntry* newIdxListEntryPtr)
  {    
        int rc;  
        //Write everything out in getSegment  
        m_segType = LIST_SUBBLOCK_TYPE;
                       
        rc =getSegment( m_pFile, ENTRY_32, newIdxListEntryPtr );         
        if (rc != NO_ERROR)
            return rc;
        //This is the new segment   
        m_curType = LIST_SUBBLOCK_TYPE;        
        m_lbid   = newIdxListEntryPtr->fbo;
        m_sbid   = newIdxListEntryPtr->sbid;
        m_entry  = newIdxListEntryPtr->entry;
        if  (m_lbid !=m_hdrLbid)
          rc = readCurBlk();
        rc = insertRid(oldRid, m_entry);
        m_entry++;
        rc = insertRid(newRid, m_entry);
        rc = updateCurCount(2);
                            
        return rc;                                              
  }
   /************************************************
    * No Change    
    * RETURN:
    *    success    - successfully created the index list header
    *    failure    - it did not create the index list header    
    ***********************************************************/  
    const int IndexList::addRidInBlk( const RID& newRid)
    {
      int maxCount, count=0;
      int rc = NO_ERROR;
      CommBlock cb;

      cb.file.oid = m_oid;
      cb.file.pFile = m_pFile;
      if (m_useNarray)
            maxCount = MAX_BLK_NARRAY_RID_CNT;
      else
            maxCount = MAX_BLK_RID_CNT;
      //Find the last block that has a space or 
      //No next block linked
      rc = findLastBlk(count);   
      if ((count ==maxCount) && (m_nextType==LIST_SIZE_TYPE))
      {//Full, also need a new segment
         IdxEmptyListEntry newIdxListEntryPtr;
         m_segType = LIST_BLOCK_TYPE;
         rc = getSegment( m_pFile,  ENTRY_BLK, &newIdxListEntryPtr); 
         m_nextLbid = ((IdxEmptyListEntry*)&newIdxListEntryPtr)->fbo;
         m_nextType = m_segType;
         m_lastIdxRidListPtr.llp=((IdxRidListPtr*)&newIdxListEntryPtr)->llp;
         rc = updateLastPtrAndParent(count);
         //the new block for insertion and count record
         m_lbid  = m_nextLbid;  
         m_sbid  = 0;
         m_entry = 0;
         m_curType = m_nextType;

         rc = readCurBlk();
         //free manager puts bad entry type at the last entry for new block
         //clean it up!
         IdxRidListPtr idxRidListPtr;
         memset(&idxRidListPtr, 0, sizeof(idxRidListPtr));         
         rc = setNextInfoFromBlk( idxRidListPtr);
         
         if (m_useNarray)
         {      
           rc = initCurBlock();
         }
         //Set the count to the beginning
         count = 0;
      }//end if FULL get new segment
      // insert in the current block at the location
      if (m_lastLbid != m_lbid)
      {
              rc = setLastLbid(m_lbid);  
      } 
      rc = insertRid(newRid, count);
      rc = updateCurCount();           
      rc = updateHdrCount();
      return rc;
   }
   /************************************************
 * No Change    
 * RETURN:
 *    success    - successfully created the index list header
 *    failure    - it did not create the index list header    
 ***********************************************************/     
 const int IndexList::findLastBlk(int& count)
 {
    int maxCount;
    int rc ;
    
    if (m_useNarray)
      maxCount = MAX_BLK_NARRAY_RID_CNT;
    else
      maxCount = MAX_BLK_RID_CNT;
     
    rc = readCurBlk();
    rc = getNextInfo(count);
    while ((count == maxCount) &&(m_nextType==LIST_BLOCK_TYPE))
    { //current is a Full link, No space to insert, go to the next one             
             m_lbid     = m_nextLbid;
             m_sbid     = 0;
             m_entry    =0;
             rc = readCurBlk();
             rc = getNextInfo(count);
    }//end of while
    return rc;
  }
    /************************************************
    * Description:
    * Find a entry for the given rowId and Key 
    * Converted                         
    * input
    *     pFile       -- File Handler     
    *     rowId       -- row id
    *     key         -- value    
    *     curIdxRidListHdrPtr - point to the header 
    * output     
    *     lbid       -- File block id
    *     sbid      -- Sub Block id
    *     entry     -- Entry id
    *   
    *     
    * return value
    *        true --found
    *        false--not found                 
    ************************************************/                
    const int  IndexList::findFirstBlk(FILE* pFile, const uint64_t& key,
                                 IdxEmptyListEntry* curIdxRidListHdrPtr,
                                 uint64_t& lbid)
    {
      int rc; 
      CommBlock cb;
      int count;
         
      cb.file.oid = m_oid;     
      cb.file.pFile = pFile;
      
      m_pFile = pFile;          
      rc = getHdrInfo(curIdxRidListHdrPtr);
      if (key!= m_curIdxRidListHdr.key) 
      {         
         return ERR_IDX_LIST_INVALID_KEY;;
      }
      int type = m_curIdxRidListHdr.nextIdxRidListPtr.type; 
      switch (type) 
      {
         case LIST_NOT_USED_TYPE://Header is not full, no sub-block linked
              lbid = INVALID_LBID;
              return NO_ERROR;  //not found 	         
         case LIST_RID_TYPE:// There is a row id here, Check!
              lbid = INVALID_LBID;
              return NO_ERROR;  //not found 	 
         case LIST_SUBBLOCK_TYPE://Not found in header
            //get the lbid sbid and entry out from the header last entry
              rc = getSubBlk(m_lbid, m_sbid, m_entry );
              m_curType = type; 
                      
              if (m_lbid != m_hdrLbid)
                      rc =readCurBlk();      
              rc = getNextInfoFromBlk(m_lastIdxRidListPtr);  
              count = m_lastIdxRidListPtr.count;  //current count  
              type  = m_lastIdxRidListPtr.type;    //block type

              if (type==LIST_BLOCK_TYPE)
                   lbid  = ((IdxEmptyListEntry*)&m_lastIdxRidListPtr)->fbo;
              else
                   lbid = INVALID_LBID;
              
              return NO_ERROR;
              break;
        default:
              //printf ("FIND FIRST BLOCK got no where, error out !! \n"); 
              break;  
      }; //end switch
      lbid =INVALID_LBID;
      return NO_ERROR;
    } //end function
   /****************************************************************
    * DESCRIPTION:
    * Private Function for setting the last Fbo on header
    * 
    ***************************************************************/    
    const int  IndexList::setNextInfoFromBlk( IdxRidListPtr& idxRidListPtr)
    {
      int rc = NO_ERROR;
      CommBlock cb;

      cb.file.oid = m_oid;
      cb.file.pFile = m_pFile;
      int pos = 0;
     
      if (m_curType == LIST_SUBBLOCK_TYPE)
          pos = LIST_SUB_LLP_POS;
      else if (m_curType == LIST_BLOCK_TYPE)
          pos = LIST_BLOCK_LLP_POS;
          
      if (m_lbid==m_hdrLbid)
      {//when sub == hdr
          setSubBlockEntry( m_hdrBlock.data, m_sbid, 
                            pos, LIST_ENTRY_WIDTH, &idxRidListPtr ); 
          m_hdrBlock.state =BLK_WRITE;                                                   
      }
      else
      {
          readCurBlk();
          if (m_lbid == m_curBlock.lbid)
          {
               setSubBlockEntry( m_curBlock.data, m_sbid, 
                                 pos, LIST_ENTRY_WIDTH, 
                                 &idxRidListPtr );
               rc = writeDBFile(cb, m_curBlock.data, m_lbid ); 
               m_curBlock.state =BLK_READ;
          }
          else
               return ERR_IDX_LIST_WRONG_LBID_WRITE;
       }                
       return rc;
    }  
  /****************************************************************
   * DESCRIPTION:
   * RETURN:
   *    success    - successfully created the index list header
   *    failure    - it did not create the index list header    
   ***********************************************************/
    const int IndexList::updateHdrSub(const RID& newRid, const uint64_t &key)
    {             
       int rc = ERR_IDX_LIST_INVALID_UP_HDR;
       CommBlock cb;
       cb.file.oid = m_oid;     
       cb.file.pFile = m_pFile;
       
       if (m_curIdxRidListHdr.firstIdxRidListEntry.type
                      == (int)LIST_NOT_USED_TYPE)
       {
                m_curIdxRidListHdr.firstIdxRidListEntry.type =LIST_RID_TYPE;
                m_curIdxRidListHdr.firstIdxRidListEntry.rid = newRid;
                m_curIdxRidListHdr.idxRidListSize.size++;
                if (m_hdrBlock.lbid == m_hdrLbid)
                    rc = writeSubBlockEntry( cb, &m_hdrBlock,  m_hdrLbid, 
                                             m_hdrSbid, m_hdrEntry,
                                             LIST_HDR_SIZE,
                                             &m_curIdxRidListHdr );
                else
                    return ERR_IDX_LIST_WRONG_LBID_WRITE;
                m_hdrBlock.state = BLK_READ;
                return rc;       
        };//Done      
        //Check Header last entry's type and go to different next step 
        m_nextType = m_curIdxRidListHdr.nextIdxRidListPtr.type;   
        switch (m_nextType) 
        {
             case LIST_NOT_USED_TYPE://Header is not full
                //insert row id into header last enty 
                  m_curIdxRidListHdr.nextIdxRidListPtr.type=LIST_RID_TYPE;
                  m_curIdxRidListHdr.nextIdxRidListPtr.llp= newRid; 
                  m_curIdxRidListHdr.idxRidListSize.size++; 
                  if (m_hdrBlock.lbid == m_hdrLbid)                  
                   rc =writeSubBlockEntry( cb, &m_hdrBlock,m_hdrLbid, 
                                           m_hdrSbid, m_hdrEntry,                                            
                                           LIST_HDR_SIZE, &m_curIdxRidListHdr);
                  else 
                   return ERR_IDX_LIST_WRONG_LBID_WRITE;
                   
                  m_hdrBlock.state = BLK_READ;
                  m_lastLbid = INVALID_LBID;
                  break;
             case LIST_RID_TYPE://Header is full, need a new sub-block  	      
                  RID oldRid ;
                  IdxEmptyListEntry newIdxListEntry;
                  oldRid = m_curIdxRidListHdr.nextIdxRidListPtr.llp;    	         	      
                  //need a sub block                   
                  m_segType = LIST_SUBBLOCK_TYPE;
                  
                  rc= moveRidsToNewSub(m_pFile, oldRid,newRid,&newIdxListEntry);
                  if (rc!=NO_ERROR)
                    return rc;
                  //update header count twice
                  m_curIdxRidListHdr.nextIdxRidListPtr.type = m_segType;
                  m_curIdxRidListHdr.nextIdxRidListPtr.llp = 
                                   ((IdxRidListHdrPtr*)&newIdxListEntry)->llp;
                  m_curIdxRidListHdr.nextIdxRidListPtr.spare= 0;
                  m_curIdxRidListHdr.idxRidListSize.size++; 
                  setSubBlockEntry(m_hdrBlock.data, m_hdrSbid, 
                                   m_hdrEntry, LIST_HDR_SIZE, 
                                   &m_curIdxRidListHdr );
                  rc = writeDBFile( cb, m_hdrBlock.data, m_hdrLbid );

                  if (rc!=NO_ERROR)
                           return rc;
                  m_hdrBlock.state = BLK_READ;        
                  m_lastLbid = INVALID_LBID;
                  if (m_curBlock.state==BLK_WRITE)
                  {
                    rc = writeDBFile( cb, m_curBlock.data, m_lbid );
                    m_curBlock.state = BLK_READ;
                  }
                   
                  break;
             case LIST_SUBBLOCK_TYPE: //first one is a sub block
             		     
                    m_lbid= ((IdxEmptyListEntry*)
                              &(m_curIdxRidListHdr.nextIdxRidListPtr))->fbo;
                    m_sbid=((IdxEmptyListEntry*)
                              &(m_curIdxRidListHdr.nextIdxRidListPtr))->sbid;
                    m_entry=((IdxEmptyListEntry*)
                              &(m_curIdxRidListHdr.nextIdxRidListPtr))->entry;     
                    m_curType = m_nextType;  
                    m_segType = LIST_BLOCK_TYPE;        
                    rc =readCurBlk();      
                    rc = getNextInfoFromBlk(m_lastIdxRidListPtr);  
                    rc = addRidInSub(newRid, m_lastIdxRidListPtr);
                    break;                              	      
             default:
                    rc=ERR_IDX_LIST_INVALID_UP_HDR;
                    break;	
         }	//end of switch
      return rc;
   }
 /************************************************
  * No Change    
  * RETURN:
  *    success    - successfully created the index list header
  *    failure    - it did not create the index list header    
  ***********************************************************/  
  const int IndexList::addRidInSub(const RID& newRid, 
                                   IdxRidListPtr& lastIdxRidListPtr)
  {
      int rc = NO_ERROR;
      int maxCount;
      int count;
      CommBlock cb;
      
      cb.file.oid   = m_oid;
      cb.file.pFile = m_pFile;
   
      m_curType  = LIST_SUBBLOCK_TYPE;
      m_segType  = LIST_BLOCK_TYPE; 
      m_nextType = lastIdxRidListPtr.type;
      
      maxCount      = MAX_SUB_RID_CNT;
      count      = lastIdxRidListPtr.count;
      //For n-array
      m_curLevel =0;
      m_curLevelPos = 0;
      m_curBlkPos = 0;
      m_parentLbid = INVALID_LBID;
         
      if ((count ==maxCount) && (m_nextType==LIST_SIZE_TYPE))
      {//Full, need a new segment
     
          IdxEmptyListEntry newIdxListEntryPtr;
          memset(&newIdxListEntryPtr, 0, sizeof(newIdxListEntryPtr));
          rc = getSegment( m_pFile,  ENTRY_BLK, &newIdxListEntryPtr);
          if (rc!=NO_ERROR)
           return rc;
          lastIdxRidListPtr.type = LIST_BLOCK_TYPE;
          lastIdxRidListPtr.llp=((IdxRidListPtr*)&newIdxListEntryPtr)->llp;
          lastIdxRidListPtr.spare=0x0;
          rc = setNextInfoFromBlk( lastIdxRidListPtr);
          //New Block initialization 
          m_lbid = newIdxListEntryPtr.fbo; 
          m_sbid = 0;
          m_entry = 0;
          m_curType =  m_segType;
          rc = readCurBlk();
          //make sure no garbage in the new block last entry
          IdxRidListPtr idxRidListPtr;
          memset(&idxRidListPtr, 0, sizeof(idxRidListPtr));
          rc = setNextInfoFromBlk( idxRidListPtr);
          count = 0;
          if (m_useNarray)
            rc = initCurBlock();
          if (m_lastLbid != m_lbid)
          {
             rc = setLastLbid(m_lbid);    
          } 
      }//end if FULL 
      else if (count <maxCount)// if less than maxCount either type =7 or 0
      {
          if (m_lastLbid != INVALID_LBID)
          {
            uint64_t zlbid = INVALID_LBID;
            rc = setLastLbid(zlbid);  
          }
      } //endif count
      else if ((count ==maxCount) && (m_nextType==LIST_BLOCK_TYPE))
      {
        m_lbid = ((IdxEmptyListEntry*)&lastIdxRidListPtr)->fbo;
        m_sbid = 0;
        m_entry = 0;
        m_curType = LIST_BLOCK_TYPE;
        rc = addRidInBlk(newRid);
        return rc;
      }
      rc = insertRid(newRid, count);// count is the position
      rc = updateCurCount();
      rc = updateHdrCount();
          
      return rc;
  }