You've already forked mariadb-columnstore-engine
							
							
				mirror of
				https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
				synced 2025-11-03 17:13:17 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			1671 lines
		
	
	
		
			45 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1671 lines
		
	
	
		
			45 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/* Copyright (C) 2014 InfiniDB, Inc.
 | 
						|
 | 
						|
   This program is free software; you can redistribute it and/or
 | 
						|
   modify it under the terms of the GNU General Public License
 | 
						|
   as published by the Free Software Foundation; version 2 of
 | 
						|
   the License.
 | 
						|
 | 
						|
   This program is distributed in the hope that it will be useful,
 | 
						|
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
   GNU General Public License for more details.
 | 
						|
 | 
						|
   You should have received a copy of the GNU General Public License
 | 
						|
   along with this program; if not, write to the Free Software
 | 
						|
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 | 
						|
   MA 02110-1301, USA. */
 | 
						|
 | 
						|
/******************************************************************************************
 | 
						|
 * $Id: we_freemgr.cpp 4450 2013-01-21 14:13:24Z rdempsey $
 | 
						|
 *
 | 
						|
 ******************************************************************************************/
 | 
						|
/** @file */
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
#include <string.h>
 | 
						|
#include <iostream>
 | 
						|
#include "we_freemgr.h"
 | 
						|
using namespace std;
 | 
						|
 | 
						|
namespace WriteEngine
 | 
						|
{
 | 
						|
/**
 | 
						|
 * Constructor
 | 
						|
 */
 | 
						|
FreeMgr::FreeMgr()
 | 
						|
{
 | 
						|
  // memset( m_workBlock.data, 0, BYTE_PER_BLOCK );
 | 
						|
 | 
						|
  // use 0 for old style, 1 for new without block list and 2 for new with block list
 | 
						|
  initType = 2;
 | 
						|
  //        setDebugLevel( DEBUG_1 );
 | 
						|
  allowExtend = 1;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Default Destructor
 | 
						|
 */
 | 
						|
FreeMgr::~FreeMgr()
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 *
 | 
						|
 * blank out all stats, set types and groups of null pointers in block zero
 | 
						|
 */
 | 
						|
const int FreeMgr::initBlockzero(DataBlock* blockZero)
 | 
						|
{
 | 
						|
  IdxEmptyListEntry Pointer;
 | 
						|
  uint64_t blankVal = 0;
 | 
						|
 | 
						|
  memset(blockZero->data, 0, sizeof(blockZero->data));
 | 
						|
 | 
						|
  nullPtr(&Pointer);
 | 
						|
  Pointer.type = EMPTY_LIST;
 | 
						|
 | 
						|
  Pointer.group = ENTRY_BLK;
 | 
						|
  setSubBlockEntry(blockZero->data, 0, calcPtrOffset(ENTRY_BLK), 8, &Pointer);
 | 
						|
 | 
						|
  Pointer.group = ENTRY_32;
 | 
						|
  setSubBlockEntry(blockZero->data, 0, calcPtrOffset(ENTRY_32), 8, &Pointer);
 | 
						|
 | 
						|
  Pointer.group = ENTRY_16;
 | 
						|
  setSubBlockEntry(blockZero->data, 0, calcPtrOffset(ENTRY_16), 8, &Pointer);
 | 
						|
 | 
						|
  Pointer.group = ENTRY_8;
 | 
						|
  setSubBlockEntry(blockZero->data, 0, calcPtrOffset(ENTRY_8), 8, &Pointer);
 | 
						|
 | 
						|
  Pointer.group = ENTRY_4;
 | 
						|
  setSubBlockEntry(blockZero->data, 0, calcPtrOffset(ENTRY_4), 8, &Pointer);
 | 
						|
 | 
						|
  Pointer.group = ENTRY_2;
 | 
						|
  setSubBlockEntry(blockZero->data, 0, calcPtrOffset(ENTRY_2), 8, &Pointer);
 | 
						|
 | 
						|
  Pointer.group = ENTRY_1;
 | 
						|
  setSubBlockEntry(blockZero->data, 0, calcPtrOffset(ENTRY_1 + ENTRY_1), 8, &Pointer);
 | 
						|
 | 
						|
  // all stat locations are contiguous and after the pointers in block zero
 | 
						|
 | 
						|
  for (int idx = calcStatOffset(ENTRY_1); idx < calcStatOffset(ENTRY_32) + 1; idx++)
 | 
						|
  {
 | 
						|
    setSubBlockEntry(blockZero->data, 0, idx, 8, &blankVal);
 | 
						|
  }
 | 
						|
 | 
						|
  return NO_ERROR;
 | 
						|
}
 | 
						|
 | 
						|
const int FreeMgr::init(CommBlock& cb, DataBlock* blockZero, int freemgrType, IdxTreeGroupType chainType,
 | 
						|
                        int startBlock, int numberBlocks)
 | 
						|
{
 | 
						|
  /**
 | 
						|
   * Use this to allocate a group of blocks or sub blocks to a free list
 | 
						|
   * startBlock is fbo NOT lbid
 | 
						|
   * This allows us to use a simple for loop to traverese the full range of blocks
 | 
						|
   *
 | 
						|
   **/
 | 
						|
 | 
						|
  int blkIdx, sbIdx;
 | 
						|
  int rc;
 | 
						|
  IdxEmptyListEntry emptyEntry;  // populate the chains with pointer to empty entries
 | 
						|
  FILE* indexFile;
 | 
						|
 | 
						|
  indexFile = cb.file.pFile;
 | 
						|
 | 
						|
  nullPtr(&emptyEntry);
 | 
						|
  emptyEntry.type = EMPTY_PTR;
 | 
						|
 | 
						|
  if (isDebug(DEBUG_3))
 | 
						|
  {
 | 
						|
    printf("\nNew style Init v2, file: %u startBlock: %i num: %i \n", cb.file.oid, (unsigned int)startBlock,
 | 
						|
           (unsigned int)numberBlocks);
 | 
						|
  }
 | 
						|
 | 
						|
  int lastBlock = numberBlocks + startBlock;
 | 
						|
 | 
						|
  if (chainType == ENTRY_BLK)
 | 
						|
  {
 | 
						|
    emptyEntry.group = ENTRY_BLK;
 | 
						|
 | 
						|
    for (blkIdx = lastBlock; blkIdx > startBlock; blkIdx--)
 | 
						|
    {
 | 
						|
      //                if( isDebug( DEBUG_1 )) { printf("Initing block %u\n", blkIdx-1);}
 | 
						|
      emptyEntry.fbo = mapLBID(cb, blkIdx - 1, rc);  // map fbo to lbid before storage
 | 
						|
 | 
						|
      if (rc != NO_ERROR)
 | 
						|
      {
 | 
						|
        printf("DBG: Init 1: Error resolving LBID for OID: %u FBO: %u\n", cb.file.oid, blkIdx - 1);
 | 
						|
        return rc;
 | 
						|
      }
 | 
						|
 | 
						|
      if (isDebug(DEBUG_3))
 | 
						|
      {
 | 
						|
        cout << "DBG: Working on block " << emptyEntry.fbo << "\n";
 | 
						|
      }
 | 
						|
 | 
						|
      emptyEntry.sbid = 0;
 | 
						|
      emptyEntry.type = EMPTY_PTR;
 | 
						|
      rc = releaseSegment(cb, blockZero, freemgrType, chainType, &emptyEntry);
 | 
						|
 | 
						|
      if (rc != NO_ERROR)
 | 
						|
      {
 | 
						|
        printf("Error releasing sb\n");
 | 
						|
        return rc;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  else if (chainType == ENTRY_32)
 | 
						|
  {
 | 
						|
    emptyEntry.group = ENTRY_32;
 | 
						|
 | 
						|
    for (blkIdx = lastBlock; blkIdx > startBlock; blkIdx--)
 | 
						|
    {
 | 
						|
      //                if( isDebug( DEBUG_1 )) { printf("Initing block %u\n", blkIdx-1);}
 | 
						|
      emptyEntry.fbo = mapLBID(cb, blkIdx - 1, rc);  // map fbo to lbid before storage
 | 
						|
 | 
						|
      if (rc != NO_ERROR)
 | 
						|
      {
 | 
						|
        printf("DBG: Init 2: Error resolving LBID for OID: %u FBO: %u\n", cb.file.oid, blkIdx - 1);
 | 
						|
        return rc;
 | 
						|
      }
 | 
						|
 | 
						|
      if (isDebug(DEBUG_3))
 | 
						|
      {
 | 
						|
        cout << "DBG: Working on block " << emptyEntry.fbo << "\n";
 | 
						|
      }
 | 
						|
 | 
						|
      for (sbIdx = BYTE_PER_BLOCK / BYTE_PER_SUBBLOCK - 1; sbIdx > -1; sbIdx--)
 | 
						|
      {
 | 
						|
        if (isDebug(DEBUG_3))
 | 
						|
        {
 | 
						|
          printf("DBG: Working on subblock %u\n", sbIdx);
 | 
						|
        }
 | 
						|
 | 
						|
        emptyEntry.sbid = sbIdx;
 | 
						|
        emptyEntry.type = EMPTY_PTR;
 | 
						|
        rc = releaseSubblock(cb, blockZero, freemgrType, &emptyEntry);
 | 
						|
 | 
						|
        if (rc != NO_ERROR)
 | 
						|
        {
 | 
						|
          printf("Error releasing sb\n");
 | 
						|
          return rc;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    if (isDebug(DEBUG_1))
 | 
						|
    {
 | 
						|
      printf("DBG: Invalid segment size %i (should be ENTRY_32 or ENTRY_BLK)\n", chainType);
 | 
						|
    }
 | 
						|
 | 
						|
    return ERR_INVALID_PARAM;
 | 
						|
  }
 | 
						|
 | 
						|
  // now write sb0 back to disk
 | 
						|
  uint64_t lbid = mapLBID(cb, 0, rc);
 | 
						|
 | 
						|
  if (rc != NO_ERROR)
 | 
						|
  {
 | 
						|
    return rc;
 | 
						|
  }
 | 
						|
 | 
						|
  rc = writeDBFile(cb, blockZero, lbid);
 | 
						|
 | 
						|
  if (rc != NO_ERROR)
 | 
						|
  {
 | 
						|
    return rc;
 | 
						|
  }
 | 
						|
 | 
						|
  return NO_ERROR;
 | 
						|
}
 | 
						|
 | 
						|
/***********************************************************
 | 
						|
 * DESCRIPTION:
 | 
						|
 *    Initializes free space lists in an new index file
 | 
						|
 * PARAMETERS:
 | 
						|
 *    indexFile - file pointer for new index file
 | 
						|
 *    freemgr_type - type of free mgr to init
 | 
						|
 * RETURN:
 | 
						|
 *    NO_ERROR if success
 | 
						|
 *
 | 
						|
 ***********************************************************/
 | 
						|
 | 
						|
const int FreeMgr::init(CommBlock& cb, int freemgrType)
 | 
						|
{
 | 
						|
  /**
 | 
						|
   * Tree has 6 chains, (1,2,4,8,16,32 entries) starting at entry 1 in sb0 of block0
 | 
						|
   * List has 3 chains (4,32,1024 entries) starting at first entry of file
 | 
						|
   *
 | 
						|
   * Starting at Block 1, add each subblock after sb0 to the free list in sb0
 | 
						|
   * then go back and build the smaller chains on demand. This way we make sure all SBs
 | 
						|
   * are in a chain somewhere.. but this is not best behaviour when allocating blocks
 | 
						|
   *
 | 
						|
   **/
 | 
						|
 | 
						|
  int rc;  // return code from file ops
 | 
						|
  DataBlock blockZero;
 | 
						|
  DataBlock workBlock;
 | 
						|
  int sbIdx;
 | 
						|
  uint64_t blkIdx;
 | 
						|
  IdxEmptyListEntry emptyEntry;   // populate the chains with pointer to empty entries
 | 
						|
  IdxEmptyListEntry nextPointer;  // pointer at end of sub-block of pointers to emptyEntries
 | 
						|
  uint64_t numBlocks;
 | 
						|
  FILE* indexFile;
 | 
						|
 | 
						|
  indexFile = cb.file.pFile;
 | 
						|
 | 
						|
  if (!indexFile)  // Make sure that we have non-null filehandle
 | 
						|
  {
 | 
						|
    //             printf("DBG: File handle is null\n");
 | 
						|
    return ERR_INVALID_PARAM;
 | 
						|
  }
 | 
						|
 | 
						|
  if (freemgrType != TREE && freemgrType != LIST)
 | 
						|
  {
 | 
						|
    //             printf("DBG: Bad type in freeMgr Init\n");
 | 
						|
    return ERR_INVALID_PARAM;
 | 
						|
  }
 | 
						|
 | 
						|
  numBlocks = getFileSize(indexFile) / BYTE_PER_BLOCK;
 | 
						|
 | 
						|
  //         printf ("DBG: File size: %lu Total blocks: %llu (%u)\n", getFileSize( indexFile ), numBlocks,
 | 
						|
  //         BYTE_PER_BLOCK); printf ("DBG: Adding sub-blocks: %llu \n",  numBlocks * 32);
 | 
						|
 | 
						|
  // Clear the list of pointers in sb0
 | 
						|
  initBlockzero(&blockZero);
 | 
						|
 | 
						|
  // initialize the non varying fields
 | 
						|
  nullPtr(&emptyEntry);
 | 
						|
  emptyEntry.type = EMPTY_PTR;
 | 
						|
  emptyEntry.group = ENTRY_32;
 | 
						|
 | 
						|
  // nextPointer identifies next sub-block with empty pointers
 | 
						|
  // initially there is no next sub-block so zero it out
 | 
						|
  nullPtr(&nextPointer);
 | 
						|
  nextPointer.type = EMPTY_LIST;
 | 
						|
  nextPointer.group = ENTRY_32;
 | 
						|
  nextPointer.entry = ENTRY_PER_SUBBLOCK - 1;  // last entry on the list.. think of the list as a stack
 | 
						|
 | 
						|
  if (initType == 0)
 | 
						|
  {
 | 
						|
    if (isDebug(DEBUG_3))
 | 
						|
    {
 | 
						|
      printf("\nOld style init\n");
 | 
						|
    }
 | 
						|
 | 
						|
    for (blkIdx = numBlocks - 1; blkIdx > 0; blkIdx--)
 | 
						|
    {
 | 
						|
      emptyEntry.fbo = blkIdx;  // map fbo to lbid before storage
 | 
						|
      //             emptyEntry.fbo  = mapLBID( cb, blkIdx, rc );// map fbo to lbid before storage
 | 
						|
      //             if (rc != NO_ERROR ){ printf("DBG: Error resolving LBID for OID: %u FBO: %llu\n",
 | 
						|
      //             cb.file.oid, blkIdx-1 ); return rc; }
 | 
						|
 | 
						|
      if (isDebug(DEBUG_3))
 | 
						|
      {
 | 
						|
        cout << "DBG: Working on block " << emptyEntry.fbo << "\n";
 | 
						|
      }
 | 
						|
 | 
						|
      memset(workBlock.data, 0, sizeof(workBlock.data));
 | 
						|
 | 
						|
      /**
 | 
						|
       * each block after zeroth block uses sb0 to store entry list
 | 
						|
       * first entry (#0) is the llp to additional sblks with entries
 | 
						|
       * entries 1-31 are pointers
 | 
						|
       **/
 | 
						|
 | 
						|
      // sb0 is used for initial map, so start at sb1
 | 
						|
      for (sbIdx = 1; sbIdx < BYTE_PER_BLOCK / BYTE_PER_SUBBLOCK; sbIdx++)
 | 
						|
      {
 | 
						|
        if (isDebug(DEBUG_3))
 | 
						|
        {
 | 
						|
          printf("DBG: Working on subblock %u\n", sbIdx);
 | 
						|
        }
 | 
						|
 | 
						|
        emptyEntry.sbid = sbIdx;
 | 
						|
        emptyEntry.type = EMPTY_PTR;
 | 
						|
        // store pointer in sb0 -  replace this with a releaseSubblock call
 | 
						|
        setSubBlockEntry(workBlock.data, 0, sbIdx, 8, &emptyEntry);
 | 
						|
 | 
						|
        if (isDebug(DEBUG_2))
 | 
						|
        {
 | 
						|
          cout << "DBG: Init sb fbo " << emptyEntry.fbo << " sbid " << emptyEntry.sbid << " entry "
 | 
						|
               << emptyEntry.entry << "\n";
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      // having stored all pointers, store linkptr
 | 
						|
      setSubBlockEntry(workBlock.data, 0, 0, 8, &nextPointer);
 | 
						|
      //             nextPointer.fbo = mapLBID( cb, blkIdx, rc ); // remember this block ID
 | 
						|
      nextPointer.fbo = blkIdx;  // remember this block ID
 | 
						|
      //             if (rc != NO_ERROR ){ printf("DBG: Error resolving LBID for OID: %u FBO: %llu\n",
 | 
						|
      //             cb.file.oid, blkIdx-1 ); return rc; }
 | 
						|
 | 
						|
      rc = writeDBFile(cb, workBlock.data, emptyEntry.fbo);
 | 
						|
 | 
						|
      if (rc != NO_ERROR)
 | 
						|
      {
 | 
						|
        return rc;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    // chain for segments of sub block size
 | 
						|
    setSubBlockEntry(blockZero.data, 0, calcPtrOffset(ENTRY_32), 8, &nextPointer);
 | 
						|
 | 
						|
    /**
 | 
						|
     * the next algorithm uses the release sub-block method and does not layout the map on particular
 | 
						|
     *boundaries.
 | 
						|
     **/
 | 
						|
  }
 | 
						|
  else if (initType == 1)  // new style - use release
 | 
						|
  {
 | 
						|
    if (isDebug(DEBUG_3))
 | 
						|
    {
 | 
						|
      printf("\nNew style\n");
 | 
						|
    }
 | 
						|
 | 
						|
    for (blkIdx = numBlocks - 1; blkIdx > 0; blkIdx--)
 | 
						|
    {
 | 
						|
      emptyEntry.fbo = blkIdx;  // map fbo to lbid before storage
 | 
						|
 | 
						|
      //                 emptyEntry.fbo  = mapLBID( cb, blkIdx, rc );// map fbo to lbid before storage
 | 
						|
      //                 if (rc != NO_ERROR ){ printf("DBG: Error resolving LBID for OID: %u FBO: %llu\n",
 | 
						|
      //                 cb.file.oid, blkIdx-1 ); return rc; }
 | 
						|
 | 
						|
      if (isDebug(DEBUG_3))
 | 
						|
      {
 | 
						|
        cout << "DBG: Working on block " << emptyEntry.fbo << "\n";
 | 
						|
      }
 | 
						|
 | 
						|
      memset(workBlock.data, 0, sizeof(workBlock.data));
 | 
						|
 | 
						|
      for (sbIdx = BYTE_PER_BLOCK / BYTE_PER_SUBBLOCK - 1; sbIdx > -1; sbIdx--)
 | 
						|
      {
 | 
						|
        if (isDebug(DEBUG_3))
 | 
						|
        {
 | 
						|
          printf("DBG: Working on subblock %u\n", sbIdx);
 | 
						|
        }
 | 
						|
 | 
						|
        emptyEntry.sbid = sbIdx;
 | 
						|
        emptyEntry.type = EMPTY_PTR;
 | 
						|
        // store pointer in sb0 -  replace this with a releaseSubblock call
 | 
						|
        rc = releaseSubblock(cb, &blockZero, freemgrType, &emptyEntry);
 | 
						|
 | 
						|
        if (rc != NO_ERROR)
 | 
						|
        {
 | 
						|
          printf("Error releasing sb\n");
 | 
						|
          return rc;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * the next algorithm uses the release sub-block method and does not layout the map on particular
 | 
						|
     *boundaries. It also allows pieces to be allocated
 | 
						|
     **/
 | 
						|
  }
 | 
						|
  else if (initType == 2)
 | 
						|
  {
 | 
						|
    /** The following calls to init accept FBO not LBID..
 | 
						|
     * This makes it easier to work on a range of blocks
 | 
						|
     **/
 | 
						|
    // use the first block of the new range for sub-block chain
 | 
						|
    // and the rest for block chain
 | 
						|
    rc = init(cb, &blockZero, freemgrType, ENTRY_32, 1, 50);
 | 
						|
 | 
						|
    if (rc != NO_ERROR)
 | 
						|
    {
 | 
						|
      return rc;
 | 
						|
    }
 | 
						|
 | 
						|
    rc = init(cb, &blockZero, freemgrType, ENTRY_BLK, 51, numBlocks - 52);
 | 
						|
 | 
						|
    if (rc != NO_ERROR)
 | 
						|
    {
 | 
						|
      return rc;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // now write sb0 back to disk
 | 
						|
  if (isDebug(DEBUG_2))
 | 
						|
  {
 | 
						|
    printf("Writing SB0 back to disk\n");
 | 
						|
    printMemSubBlock(&blockZero, 0);
 | 
						|
  }
 | 
						|
 | 
						|
  uint64_t lbid = mapLBID(cb, 0, rc);
 | 
						|
 | 
						|
  if (rc != NO_ERROR)
 | 
						|
  {
 | 
						|
    return rc;
 | 
						|
  }
 | 
						|
 | 
						|
  rc = writeDBFile(cb, blockZero.data, lbid);
 | 
						|
 | 
						|
  if (rc != NO_ERROR)
 | 
						|
  {
 | 
						|
    return rc;
 | 
						|
  }
 | 
						|
 | 
						|
  return NO_ERROR;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * DESCRIPTION:
 | 
						|
 *    Assign segment- public method used to get a free segment for use
 | 
						|
 * PARAMETERS:
 | 
						|
 *   indexFile - file pointer
 | 
						|
 *   blockZero - in memory copy of blockZero
 | 
						|
 *   freemgr_type - either TREE or LIST
 | 
						|
 *   segmentType - group type
 | 
						|
 *   assignPtr - the assigned ptr
 | 
						|
 *
 | 
						|
 * RETURN:
 | 
						|
 *    NO_ERROR if success
 | 
						|
 *    error no if fail
 | 
						|
 **/
 | 
						|
 | 
						|
const int FreeMgr::assignSegment(CommBlock& cb, DataBlock* blockZero, const int freemgr_type,
 | 
						|
                                 const IdxTreeGroupType segmentType, IdxEmptyListEntry* assignPtr)
 | 
						|
{
 | 
						|
  int rc;  // return code from file ops
 | 
						|
  DataBlock workBlock;
 | 
						|
  int listOffset;  // entry in block zero of head pointer
 | 
						|
  IdxEmptyListEntry emptyEntry;
 | 
						|
  IdxEmptyListEntry emptyPtr;
 | 
						|
  IdxEmptyListEntry emptyMap;
 | 
						|
  uint64_t numBlocks;
 | 
						|
  IdxEmptyListEntry newSb;
 | 
						|
  FILE* indexFile;
 | 
						|
 | 
						|
  indexFile = cb.file.pFile;
 | 
						|
 | 
						|
  if (isDebug(DEBUG_3))
 | 
						|
  {
 | 
						|
    printf("DBG: Assign ENTRY_%i segment in %s\n", 1 << (unsigned int)segmentType,
 | 
						|
           (freemgr_type == LIST) ? "LIST" : "TREE");
 | 
						|
  }
 | 
						|
 | 
						|
  /* Check all input parameters are ok   */
 | 
						|
  if (!blockZero)
 | 
						|
  {
 | 
						|
    if (isDebug(DEBUG_1))
 | 
						|
    {
 | 
						|
      printf("DBG: Bad pointer: blockZero is zero\n");
 | 
						|
    }
 | 
						|
 | 
						|
    return ERR_INVALID_PARAM;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!assignPtr)
 | 
						|
  {
 | 
						|
    if (isDebug(DEBUG_1))
 | 
						|
    {
 | 
						|
      printf("DBG: Bad pointer: assignPtr is zero\n");
 | 
						|
    }
 | 
						|
 | 
						|
    return ERR_INVALID_PARAM;
 | 
						|
  }
 | 
						|
 | 
						|
  if (freemgr_type != TREE && freemgr_type != LIST)
 | 
						|
  {
 | 
						|
    if (isDebug(DEBUG_0))
 | 
						|
    {
 | 
						|
      printf("DBG: assignSegment: Must be TREE or LIST\n");
 | 
						|
    }
 | 
						|
 | 
						|
    return ERR_INVALID_PARAM;
 | 
						|
  }
 | 
						|
 | 
						|
  numBlocks = getFileSize(indexFile) / BYTE_PER_BLOCK;
 | 
						|
 | 
						|
  // find the start of the chain
 | 
						|
  if (segmentType == ENTRY_32)
 | 
						|
  {
 | 
						|
    rc = assignSubblock(cb, blockZero, freemgr_type, assignPtr);
 | 
						|
 | 
						|
    if (rc != NO_ERROR)
 | 
						|
    {
 | 
						|
      if (isDebug(DEBUG_1))
 | 
						|
      {
 | 
						|
        printf("DBG: Error assigning sb (rc=%i)\n", rc);
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    return rc;
 | 
						|
  }
 | 
						|
 | 
						|
  listOffset = calcPtrOffset(segmentType);
 | 
						|
 | 
						|
  if (freemgr_type == LIST && !(segmentType == ENTRY_4 || segmentType == ENTRY_BLK))
 | 
						|
  {
 | 
						|
    if (isDebug(DEBUG_1))
 | 
						|
    {
 | 
						|
      printf("DBG: Assign segment size illegal %i\n", (unsigned int)segmentType);
 | 
						|
    }
 | 
						|
 | 
						|
    return ERR_INVALID_PARAM;  // should not have got here so quit with error
 | 
						|
  }
 | 
						|
 | 
						|
  // read Empty Map in sb0
 | 
						|
  getSubBlockEntry(blockZero, 0, listOffset, 8, &emptyPtr);
 | 
						|
 | 
						|
  if (isDebug(DEBUG_2))
 | 
						|
  {
 | 
						|
    cout << "DBG: Empty map ENTRY_" << (1 << segmentType) << "  was fbo " << emptyPtr.fbo << " sbid "
 | 
						|
         << (unsigned int)emptyPtr.sbid << " entry " << (unsigned int)emptyPtr.entry << "\n";
 | 
						|
  }
 | 
						|
 | 
						|
  /*       if (emptyPtr.fbo > numBlocks)
 | 
						|
         {
 | 
						|
             printf("DBG: Weirdness in assignSegment.. emptyPtr.fbo > numBlocks\n");
 | 
						|
             return ERR_FM_BAD_FBO;
 | 
						|
         }*/
 | 
						|
 | 
						|
  // check to see if queue has been built
 | 
						|
  // if not then assign a container block, add LLP in entry 0 pointing to nothing
 | 
						|
  if (emptyPtr.fbo == 0)
 | 
						|
  {
 | 
						|
    if (isDebug(DEBUG_3))
 | 
						|
    {
 | 
						|
      printf("DBG: Need to add sb to chain and entries to sb\n");
 | 
						|
    }
 | 
						|
 | 
						|
    // cannot assign more space to block list from a smaller list.. need to extend the file
 | 
						|
    if (segmentType == ENTRY_BLK)
 | 
						|
    {
 | 
						|
      if (isDebug(DEBUG_1))
 | 
						|
      {
 | 
						|
        printf("Out of space in BLOCK list, quitting\n");
 | 
						|
      }
 | 
						|
 | 
						|
      rc = extendFreespace(cb, blockZero, freemgr_type);
 | 
						|
 | 
						|
      if (rc != NO_ERROR)
 | 
						|
      {
 | 
						|
        if (isDebug(DEBUG_3))
 | 
						|
        {
 | 
						|
          printf("DBG: Error extending file\n");
 | 
						|
        }
 | 
						|
 | 
						|
        return rc;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    rc = assignSubblock(cb, blockZero, freemgr_type, &emptyPtr);
 | 
						|
 | 
						|
    if (rc != NO_ERROR)
 | 
						|
    {
 | 
						|
      printf("DBG: Error extending chain\n");
 | 
						|
      return rc;
 | 
						|
    }
 | 
						|
 | 
						|
    rc = readDBFile(cb, workBlock.data, emptyPtr.fbo);
 | 
						|
 | 
						|
    if (rc != NO_ERROR) /*printf("DBG: Error reading newly allocated sb\n");*/
 | 
						|
    {
 | 
						|
      return rc;
 | 
						|
    }
 | 
						|
 | 
						|
    // update map to point to new bucket
 | 
						|
    setSubBlockEntry(blockZero, 0, listOffset, 8, &emptyPtr);
 | 
						|
 | 
						|
    nullPtr(&emptyEntry);
 | 
						|
    emptyEntry.type = EMPTY_LIST;
 | 
						|
    emptyEntry.group = segmentType;
 | 
						|
 | 
						|
    setSubBlockEntry(workBlock.data, emptyPtr.sbid, 0, 8, &emptyEntry);  // store head ptr
 | 
						|
 | 
						|
    rc = writeDBFile(cb, workBlock.data, emptyPtr.fbo);
 | 
						|
 | 
						|
    if (rc != NO_ERROR)
 | 
						|
    {
 | 
						|
      return rc;
 | 
						|
    }
 | 
						|
 | 
						|
    if (isDebug(DEBUG_2))
 | 
						|
    {
 | 
						|
      cout << "DBG: Added fbo " << emptyPtr.fbo << " sbid " << (unsigned int)emptyPtr.sbid
 | 
						|
           << " as bucket to chain ENTRY_" << (1 << segmentType) << "in"
 | 
						|
           << ((freemgr_type == LIST) ? "LIST" : "TREE") << "\n";
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // follow the chain to the head container
 | 
						|
  rc = readDBFile(cb, workBlock.data, emptyPtr.fbo);
 | 
						|
 | 
						|
  if (rc != NO_ERROR)
 | 
						|
  {
 | 
						|
    if (isDebug(DEBUG_1))
 | 
						|
    {
 | 
						|
      cout << "DBG: Error reading block (" << emptyPtr.fbo << ") during segmentAssign: rc is " << rc;
 | 
						|
    }
 | 
						|
 | 
						|
    return rc;
 | 
						|
  }
 | 
						|
 | 
						|
  getSubBlockEntry(&workBlock, emptyPtr.sbid, emptyPtr.entry, 8, &emptyEntry);
 | 
						|
 | 
						|
  if ((emptyEntry.type != EMPTY_LIST) && (emptyEntry.type != EMPTY_PTR))
 | 
						|
  {
 | 
						|
    if (isDebug(DEBUG_0))
 | 
						|
    {
 | 
						|
      printf("WTF: Bad entry in ENTRY_%i chain - type is %i (expected %i or %i)\n", 1 << segmentType,
 | 
						|
             (unsigned int)emptyEntry.type, EMPTY_PTR, EMPTY_LIST);
 | 
						|
      printMemSubBlock(&workBlock, emptyPtr.sbid);
 | 
						|
    }
 | 
						|
 | 
						|
    if (isDebug(DEBUG_2))
 | 
						|
    {
 | 
						|
      cout << "DBG: fbo " << emptyEntry.fbo << " sbid " << (unsigned int)emptyEntry.sbid << " entry "
 | 
						|
           << (unsigned int)emptyEntry.entry << " chain ENTRY_" << (1 << segmentType) << "in"
 | 
						|
           << ((freemgr_type == LIST) ? "LIST" : "TREE") << "\n";
 | 
						|
    }
 | 
						|
 | 
						|
    return ERR_FM_BAD_TYPE;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((emptyEntry.fbo == 0) && (emptyEntry.type == EMPTY_PTR))
 | 
						|
  {
 | 
						|
    if (isDebug(DEBUG_0))
 | 
						|
    {
 | 
						|
      printf("DBG: Bad entry in %i list - found EMPTY_PTR but indicates block 0\n", 1 << segmentType);
 | 
						|
    }
 | 
						|
 | 
						|
    return ERR_FM_BAD_TYPE;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((emptyEntry.fbo == 0) && (emptyEntry.type == EMPTY_LIST))
 | 
						|
  {
 | 
						|
    /**
 | 
						|
     * if at the end of the rainbow, in a bucket with no entries, fill the bucket
 | 
						|
     * Allocate a sub block and split it into parts
 | 
						|
     **/
 | 
						|
 | 
						|
    // cannot assign more space to block list from a smaller list.. need to extend the file
 | 
						|
    if (segmentType == ENTRY_BLK)
 | 
						|
    {
 | 
						|
      if (isDebug(DEBUG_1))
 | 
						|
      {
 | 
						|
        printf("\nNeed to extend block\n");
 | 
						|
      }
 | 
						|
 | 
						|
      if (isDebug(DEBUG_1))
 | 
						|
      {
 | 
						|
        printf("Out of space in BLOCK list\n");
 | 
						|
      }
 | 
						|
 | 
						|
      rc = extendFreespace(cb, blockZero, freemgr_type);
 | 
						|
 | 
						|
      if (rc != NO_ERROR)
 | 
						|
      {
 | 
						|
        if (isDebug(DEBUG_3))
 | 
						|
        {
 | 
						|
          printf("DBG: Error extending file\n");
 | 
						|
        }
 | 
						|
 | 
						|
        return rc;
 | 
						|
      }
 | 
						|
 | 
						|
      getSubBlockEntry(blockZero, 0, listOffset, 8, &emptyPtr);
 | 
						|
      rc = readDBFile(cb, workBlock.data, emptyPtr.fbo);
 | 
						|
      getSubBlockEntry(&workBlock, emptyPtr.sbid, emptyPtr.entry, 8, &emptyEntry);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
      rc = assignSubblock(cb, blockZero, freemgr_type, &newSb);
 | 
						|
 | 
						|
      if (rc != NO_ERROR)
 | 
						|
      {
 | 
						|
        //                printf("DBG: Error extending chain\n");
 | 
						|
        return rc;
 | 
						|
      }
 | 
						|
 | 
						|
      if (newSb.entry != 0)
 | 
						|
      {
 | 
						|
        printf("WTF: Entry should be 0 after assign from sb list, instead is %i", (unsigned int)newSb.entry);
 | 
						|
        return ERR_FM_ASSIGN_ERR;
 | 
						|
      }
 | 
						|
 | 
						|
      if (isDebug(DEBUG_2))
 | 
						|
      {
 | 
						|
        cout << "DBG: added fbo " << newSb.fbo << " sbid " << (unsigned int)newSb.sbid << " entry "
 | 
						|
             << (unsigned)newSb.entry << " to " << segmentType << " list - need to split "
 | 
						|
             << (1 << (ENTRY_32 - segmentType)) << "times\n";
 | 
						|
      }
 | 
						|
 | 
						|
      newSb.entry = 0;
 | 
						|
      newSb.group = segmentType;
 | 
						|
      newSb.type = EMPTY_PTR;
 | 
						|
      emptyEntry = newSb;
 | 
						|
 | 
						|
      int idx, inc;
 | 
						|
      inc = 1 << segmentType;
 | 
						|
 | 
						|
      for (idx = 0; idx < ENTRY_PER_SUBBLOCK - inc; idx += inc)
 | 
						|
      {
 | 
						|
        if (isDebug(DEBUG_3))
 | 
						|
        {
 | 
						|
          printf("DBG: split..%i-%i\n", idx, idx + inc - 1);
 | 
						|
        }
 | 
						|
 | 
						|
        newSb.entry = idx;
 | 
						|
        releaseSegment(cb, blockZero, freemgr_type, segmentType, &newSb);
 | 
						|
      }
 | 
						|
 | 
						|
      emptyEntry.entry = idx;
 | 
						|
 | 
						|
      if (isDebug(DEBUG_3))
 | 
						|
      {
 | 
						|
        printf("DBG: split and return..%i-%i\n", idx, idx + inc - 1);
 | 
						|
      }
 | 
						|
 | 
						|
      if (isDebug(DEBUG_2))
 | 
						|
      {
 | 
						|
        cout << "DBG: Assigned fbo " << emptyEntry.fbo << " sbid " << (unsigned int)emptyEntry.sbid
 | 
						|
             << " entry " << (unsigned int)emptyEntry.entry << " to chain ENTRY_" << (1 << segmentType)
 | 
						|
             << "\n";
 | 
						|
      }
 | 
						|
 | 
						|
      memcpy(assignPtr, &emptyEntry, 8);
 | 
						|
 | 
						|
      uint64_t count;
 | 
						|
      getSubBlockEntry(blockZero, 0, calcStatOffset(segmentType), 8, &count);
 | 
						|
      count--;
 | 
						|
      setSubBlockEntry(blockZero, 0, calcStatOffset(segmentType), 8, &count);
 | 
						|
 | 
						|
      return NO_ERROR;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * got here because we didn't need to populate a chain and did not fall into any traps
 | 
						|
   * so either we are at the end of bucket or we have a valid entry
 | 
						|
   **/
 | 
						|
  if (emptyEntry.type == EMPTY_LIST)  // reached end of this segment (should release it for re-use)
 | 
						|
  {
 | 
						|
    /**
 | 
						|
     * release bucket
 | 
						|
     **/
 | 
						|
    if (isDebug(DEBUG_2))
 | 
						|
    {
 | 
						|
      cout << "DBG: Need to release sb fbo " << emptyPtr.fbo << " sbid " << emptyPtr.sbid
 | 
						|
           << " from chain ENTRY_" << (1 << segmentType) << " in "
 | 
						|
           << ((freemgr_type == LIST) ? "LIST" : "TREE") << "\n";
 | 
						|
    }
 | 
						|
 | 
						|
    // when we stored the ptr in the empty map, we tweaked group, must change it back
 | 
						|
    emptyPtr.type = EMPTY_PTR;
 | 
						|
    emptyPtr.group = ENTRY_32;
 | 
						|
    rc = releaseSubblock(cb, blockZero, freemgr_type, &emptyPtr);
 | 
						|
 | 
						|
    if (rc != NO_ERROR)
 | 
						|
    {
 | 
						|
      printf("Error releasing sb\n");
 | 
						|
      return rc;
 | 
						|
    }
 | 
						|
 | 
						|
    emptyPtr = emptyEntry;
 | 
						|
    rc = readDBFile(cb, workBlock.data, emptyPtr.fbo);
 | 
						|
 | 
						|
    if (rc != NO_ERROR)
 | 
						|
    {
 | 
						|
      printf("DBG: Error following chain\n");
 | 
						|
      return rc;
 | 
						|
    }
 | 
						|
 | 
						|
    getSubBlockEntry(&workBlock, emptyPtr.sbid, emptyPtr.entry, 8, &emptyEntry);
 | 
						|
  }
 | 
						|
 | 
						|
  if (emptyEntry.type == EMPTY_PTR)
 | 
						|
  {
 | 
						|
    emptyPtr.entry--;
 | 
						|
    blockZero->dirty = 1;
 | 
						|
    setSubBlockEntry(blockZero, 0, listOffset, 8, &emptyPtr);
 | 
						|
 | 
						|
    if (isDebug(DEBUG_3))
 | 
						|
    {
 | 
						|
      printf("DBG: Empty entry is now %u\n", (unsigned int)emptyPtr.entry);
 | 
						|
    }
 | 
						|
 | 
						|
    if (isDebug(DEBUG_2))
 | 
						|
    {
 | 
						|
      cout << "DBG: Assigned fbo " << emptyEntry.fbo << " sbid " << emptyEntry.sbid << " entry "
 | 
						|
           << emptyEntry.entry << " from chain ENTRY_" << (1 << segmentType) << "\n";
 | 
						|
      cout << "DBG: Empty map ENTRY_" << (1 << segmentType) << " now fbo " << emptyPtr.fbo << " sbid "
 | 
						|
           << emptyPtr.sbid << " entry " << emptyPtr.entry << "\n";
 | 
						|
    }
 | 
						|
 | 
						|
    memcpy(assignPtr, &emptyEntry, 8);
 | 
						|
 | 
						|
    // -- workblock may have changed on disk since it was read.. making the writeDBfile dangerous without a
 | 
						|
    // readDBfile first
 | 
						|
    nullPtr(&emptyMap);  // zero out the entry
 | 
						|
    readDBFile(cb, &workBlock, emptyPtr.fbo);
 | 
						|
    setSubBlockEntry(workBlock.data, emptyPtr.sbid, emptyPtr.entry + 1, 8, &emptyMap);
 | 
						|
    rc = writeDBFile(cb, &workBlock, emptyPtr.fbo);
 | 
						|
    // --
 | 
						|
 | 
						|
    uint64_t count;
 | 
						|
    getSubBlockEntry(blockZero, 0, calcStatOffset(segmentType), 8, &count);
 | 
						|
    count--;
 | 
						|
    setSubBlockEntry(blockZero, 0, calcStatOffset(segmentType), 8, &count);
 | 
						|
 | 
						|
    return NO_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  return ERR_FM_ASSIGN_ERR;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * DESCRIPTION:
 | 
						|
 *    Assign sub-block - private method used to manage sub-blocks in list
 | 
						|
 * PARAMETERS:
 | 
						|
 *   indexFile - file pointer
 | 
						|
 *   blockZero - in memory copy of blockZero
 | 
						|
 *   freemgr_type - either TREE or LIST
 | 
						|
 *   assignPtr - the assigned ptr
 | 
						|
 *
 | 
						|
 * RETURN:
 | 
						|
 *    NO_ERROR if success
 | 
						|
 *    error no if fail
 | 
						|
 **/
 | 
						|
 | 
						|
const int FreeMgr::assignSubblock(CommBlock& cb, DataBlock* blockZero, const int freemgrType,
 | 
						|
                                  IdxEmptyListEntry* assignPtr)
 | 
						|
{
 | 
						|
  int rc;  // return code from file ops
 | 
						|
  DataBlock workBlock, tempBlock;
 | 
						|
  int listOffset;  // entry in block zero of head pointer
 | 
						|
  IdxEmptyListEntry emptyEntry;
 | 
						|
  IdxEmptyListEntry emptyPtr, emptyMap;
 | 
						|
  IdxEmptyListEntry newBlock;
 | 
						|
  uint64_t numBlocks;
 | 
						|
  FILE* indexFile;
 | 
						|
 | 
						|
  indexFile = cb.file.pFile;
 | 
						|
 | 
						|
  /**
 | 
						|
   * Separated subblock assignment out from general segment assignment
 | 
						|
   * Reduces the hoops to jump through
 | 
						|
   **/
 | 
						|
 | 
						|
  numBlocks = getFileSize(indexFile) / BYTE_PER_BLOCK;
 | 
						|
 | 
						|
  if (isDebug(DEBUG_3))
 | 
						|
  {
 | 
						|
    printf("DBG: Assign subblock \n");
 | 
						|
  }
 | 
						|
 | 
						|
  // find the start of the chain
 | 
						|
  listOffset = calcPtrOffset(ENTRY_32);
 | 
						|
 | 
						|
  getSubBlockEntry(blockZero, 0, listOffset, 8, &emptyPtr);
 | 
						|
 | 
						|
  if (isDebug(DEBUG_2))
 | 
						|
  {
 | 
						|
    cout << "DBG: EM (start assign) sb fbo " << emptyPtr.fbo << " sbid " << emptyPtr.sbid << " entry "
 | 
						|
         << emptyPtr.entry << "\n";
 | 
						|
  }
 | 
						|
 | 
						|
  if (emptyPtr.type != EMPTY_LIST)
 | 
						|
  {
 | 
						|
    return ERR_FM_BAD_TYPE;
 | 
						|
  }
 | 
						|
 | 
						|
  //        if (emptyPtr.fbo > numBlocks)
 | 
						|
  //        {
 | 
						|
  //            if( isDebug( DEBUG_1 )) { printf("DBG: Weirdness in assignSubblock.. emptyPtr.fbo >
 | 
						|
  //            numBlocks\n"); } return ERR_FM_BAD_FBO;
 | 
						|
  //        }
 | 
						|
 | 
						|
  // follow the chain to the empty entry
 | 
						|
  rc = readDBFile(cb, workBlock.data, emptyPtr.fbo);
 | 
						|
 | 
						|
  if (rc != NO_ERROR)
 | 
						|
  {
 | 
						|
    //            printf("DBG: RC Weirdness: rc is %i", rc);
 | 
						|
    return rc;
 | 
						|
  }
 | 
						|
 | 
						|
  getSubBlockEntry(&workBlock, emptyPtr.sbid, emptyPtr.entry, 8, &emptyEntry);
 | 
						|
 | 
						|
  if (isDebug(DEBUG_2))
 | 
						|
  {
 | 
						|
    cout << "DBG: Next avail sb fbo " << emptyEntry.fbo << " sbid "
 | 
						|
         << " entry " << emptyEntry.entry << "\n";
 | 
						|
  }
 | 
						|
 | 
						|
  if (emptyEntry.fbo == 0)  // then nowhere to go.. exit
 | 
						|
  {
 | 
						|
    // if( isDebug( DEBUG_1 )) { printf("DBG: No space in subblock list\n"); }
 | 
						|
    if (isDebug(DEBUG_2))
 | 
						|
    {
 | 
						|
      cout << "DBG: fbo " << emptyEntry.fbo << " sbid " << emptyEntry.sbid << " entry " << emptyEntry.entry
 | 
						|
           << "\n";
 | 
						|
    }
 | 
						|
 | 
						|
    //-- try and assign from BLOCK list
 | 
						|
    //                printf("Go ask for a block\n");
 | 
						|
    rc = assignSegment(cb, blockZero, freemgrType, ENTRY_BLK, &newBlock);
 | 
						|
 | 
						|
    //                rc = extendFreespace( indexFile, blockZero, freemgrType );
 | 
						|
 | 
						|
    if (rc != NO_ERROR)
 | 
						|
    {
 | 
						|
      if (isDebug(DEBUG_1))
 | 
						|
      {
 | 
						|
        printf("DBG: Could not get block from block list\n");
 | 
						|
      }
 | 
						|
 | 
						|
      return rc;
 | 
						|
    }
 | 
						|
 | 
						|
    // got a block so now split it
 | 
						|
    newBlock.entry = 0;
 | 
						|
    newBlock.group = ENTRY_32;
 | 
						|
    newBlock.type = EMPTY_PTR;
 | 
						|
    emptyEntry = newBlock;
 | 
						|
 | 
						|
    //-- assign almost all sub blocks - keep last one
 | 
						|
    int sbIdx;
 | 
						|
 | 
						|
    for (sbIdx = BYTE_PER_BLOCK / BYTE_PER_SUBBLOCK - 1; sbIdx > 0; sbIdx--)
 | 
						|
    {
 | 
						|
      if (isDebug(DEBUG_3))
 | 
						|
      {
 | 
						|
        cout << "DBG: Working on fbo " << newBlock.fbo << " sbid " << sbIdx << "\n";
 | 
						|
      }
 | 
						|
 | 
						|
      emptyEntry.sbid = sbIdx;
 | 
						|
      emptyEntry.type = EMPTY_PTR;
 | 
						|
      rc = releaseSubblock(cb, blockZero, freemgrType, &emptyEntry);
 | 
						|
 | 
						|
      if (rc != NO_ERROR)
 | 
						|
      {
 | 
						|
        printf("DBG: Error releasing sb\n");
 | 
						|
        return rc;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    emptyEntry.sbid = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((emptyEntry.type != EMPTY_LIST) && (emptyEntry.type != EMPTY_PTR))
 | 
						|
  {
 | 
						|
    if (isDebug(DEBUG_0))
 | 
						|
    {
 | 
						|
      printf("WTF: Bad entry in in subblock list- type is %i (expected %i or %i)\n",
 | 
						|
             (unsigned int)emptyEntry.type, EMPTY_PTR, EMPTY_LIST);
 | 
						|
    }
 | 
						|
 | 
						|
    if (isDebug(DEBUG_2))
 | 
						|
    {
 | 
						|
      cout << "DBG: fbo " << emptyEntry.fbo << " sbid " << emptyEntry.sbid << " entry " << emptyEntry.entry
 | 
						|
           << "\n";
 | 
						|
    }
 | 
						|
 | 
						|
    return ERR_FM_BAD_TYPE;
 | 
						|
  }
 | 
						|
 | 
						|
  if (emptyEntry.type == EMPTY_PTR)
 | 
						|
  {
 | 
						|
    // this is what we expect normally
 | 
						|
    emptyPtr.entry--;  // only decrement if we didn't just drain a bucket
 | 
						|
    setSubBlockEntry(blockZero, 0, listOffset, 8, &emptyPtr);
 | 
						|
    memcpy(assignPtr, &emptyEntry, 8);
 | 
						|
  }
 | 
						|
  else if (emptyEntry.type == EMPTY_LIST && emptyPtr.entry == 0)
 | 
						|
  {
 | 
						|
    if (emptyPtr.entry > 0)
 | 
						|
      printf("\nWTF!! %i\n", (unsigned int)emptyPtr.entry);
 | 
						|
 | 
						|
    // reached end of this bucket (should release it for re-use)
 | 
						|
    // this is not the typical case..
 | 
						|
    if (isDebug(DEBUG_3))
 | 
						|
    {
 | 
						|
      cout << "DBG: Drained bucket sb fbo " << emptyPtr.fbo << " sbid " << emptyPtr.sbid << " entry "
 | 
						|
           << emptyPtr.entry << "\n";
 | 
						|
    }
 | 
						|
 | 
						|
    // blank the llp
 | 
						|
    rc = readDBFile(cb, tempBlock.data, emptyPtr.fbo);
 | 
						|
 | 
						|
    if (rc != NO_ERROR)
 | 
						|
    {
 | 
						|
      if (isDebug(DEBUG_1))
 | 
						|
      {
 | 
						|
        cout << "DBG: File error during releaseSubblock, fbo/lbid: " << emptyPtr.fbo << "\n";
 | 
						|
      }
 | 
						|
 | 
						|
      return rc;
 | 
						|
    }
 | 
						|
 | 
						|
    nullPtr(&emptyMap);  // zero out the entry
 | 
						|
 | 
						|
    setSubBlockEntry(tempBlock.data, emptyPtr.sbid, 0, 8, &emptyMap);
 | 
						|
    rc = writeDBFile(cb, &tempBlock, emptyPtr.fbo);
 | 
						|
 | 
						|
    if (rc != NO_ERROR)
 | 
						|
    {
 | 
						|
      return rc;
 | 
						|
    }
 | 
						|
 | 
						|
    memcpy(assignPtr, &emptyPtr, 8);
 | 
						|
    assignPtr->type = EMPTY_PTR;
 | 
						|
 | 
						|
    if (isDebug(DEBUG_2))
 | 
						|
    {
 | 
						|
      cout << "DBG: Change head pointer to fbo " << emptyEntry.fbo << " sbid " << emptyEntry.sbid << " entry "
 | 
						|
           << emptyEntry.entry << "\n";
 | 
						|
    }
 | 
						|
 | 
						|
    setSubBlockEntry(blockZero, 0, listOffset, 8, &emptyEntry);
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    printf("DBG: Weirdness - not list and not ptr\n");
 | 
						|
  }
 | 
						|
 | 
						|
  //            printf("DBG: Assigned sb fbo %llu sbid %u entry %u\n", assignPtr->fbo, (unsigned
 | 
						|
  //            int)assignPtr->sbid, (unsigned int)assignPtr->entry);
 | 
						|
 | 
						|
  getSubBlockEntry(blockZero, 0, listOffset, 8, &emptyMap);
 | 
						|
 | 
						|
  if (isDebug(DEBUG_3))
 | 
						|
  {
 | 
						|
    cout << "DBG: EM (sb assign 1) sb fbo " << emptyMap.fbo << " sbid " << emptyMap.sbid << " entry "
 | 
						|
         << emptyMap.entry << "\n";
 | 
						|
  }
 | 
						|
 | 
						|
  blockZero->dirty = 1;
 | 
						|
 | 
						|
  uint64_t count;
 | 
						|
  getSubBlockEntry(blockZero, 0, calcStatOffset(ENTRY_32), 8, &count);
 | 
						|
  count--;
 | 
						|
  setSubBlockEntry(blockZero, 0, calcStatOffset(ENTRY_32), 8, &count);
 | 
						|
 | 
						|
  // -- workblock may have changed on disk since it was read.. making the writeDBfile dangerous without a
 | 
						|
  // readDBfile first
 | 
						|
  nullPtr(&emptyMap);  // zero out the entry
 | 
						|
  readDBFile(cb, &workBlock, emptyPtr.fbo);
 | 
						|
  setSubBlockEntry(workBlock.data, emptyPtr.sbid, emptyPtr.entry + 1, 8, &emptyMap);
 | 
						|
  rc = writeDBFile(cb, &workBlock, emptyPtr.fbo);
 | 
						|
  // --
 | 
						|
  //            if( isDebug( DEBUG_3 )) { printf("DBG: Assign subblock -- all done\n"); }
 | 
						|
 | 
						|
  return NO_ERROR;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * DESCRIPTION:
 | 
						|
 *    Release a segment back to the list
 | 
						|
 * PARAMETERS:
 | 
						|
 *   indexFile - file pointer
 | 
						|
 *   blockZero - in memory copy of blockZero
 | 
						|
 *   freemgr_type - either TREE or LIST
 | 
						|
 *   segmentType - group type
 | 
						|
 *   assignPtr - the assigned ptr
 | 
						|
 *
 | 
						|
 * RETURN:
 | 
						|
 *    NO_ERROR if success
 | 
						|
 *    error no if fail
 | 
						|
 **/
 | 
						|
 | 
						|
const int FreeMgr::releaseSegment(CommBlock& cb, DataBlock* blockZero, const int freemgr_type,
 | 
						|
                                  const IdxTreeGroupType segmentType, IdxEmptyListEntry* assignPtr)
 | 
						|
{
 | 
						|
  int rc;  // return code from file ops
 | 
						|
  DataBlock workBlock;
 | 
						|
  DataBlock extraBlock;
 | 
						|
  int listOffset;  // entry in block zero of head pointer
 | 
						|
  IdxEmptyListEntry emptyPtr;
 | 
						|
  IdxEmptyListEntry newSb;
 | 
						|
  uint64_t numBlocks;
 | 
						|
  FILE* indexFile;
 | 
						|
 | 
						|
  indexFile = cb.file.pFile;
 | 
						|
 | 
						|
  if (!assignPtr)
 | 
						|
  {
 | 
						|
    //            printf ("DBG: Bad pointer: assignPtr is zero\n");
 | 
						|
    return ERR_INVALID_PARAM;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!blockZero)
 | 
						|
  {
 | 
						|
    //            printf ("DBG: Bad pointer: blockZero is zero\n");
 | 
						|
    return ERR_INVALID_PARAM;
 | 
						|
  }
 | 
						|
 | 
						|
  if (isDebug(DEBUG_3))
 | 
						|
  {
 | 
						|
    printf("DBG: release ENTRY_%i segment \n", 1 << (unsigned int)segmentType);
 | 
						|
  }
 | 
						|
 | 
						|
  if (isDebug(DEBUG_2))
 | 
						|
  {
 | 
						|
    cout << "DBG: releasing fbo " << assignPtr->fbo << " sbid " << assignPtr->sbid << " entry "
 | 
						|
         << assignPtr->entry << " from " << ((freemgr_type == LIST) ? "LIST" : "TREE") << " chain ENTRY_"
 | 
						|
         << (1 << segmentType) << " (type is "
 | 
						|
         << ((assignPtr->type == EMPTY_PTR) ? "EMPTY_PTR" : "Not EMPTY_PTR") << ")\n";
 | 
						|
  }
 | 
						|
 | 
						|
  numBlocks = getFileSize(indexFile) / BYTE_PER_BLOCK;
 | 
						|
 | 
						|
  /*       if (assignPtr->fbo > numBlocks)
 | 
						|
  {
 | 
						|
      if( isDebug( DEBUG_1 )) { printf("DBG: Weirdness in releaseSegment.. assignPtr.fbo > numBlocks (%llu
 | 
						|
  %llu)\n", assignPtr->fbo, numBlocks );}; return ERR_FM_BAD_FBO;
 | 
						|
  }*/
 | 
						|
 | 
						|
  if (assignPtr->type != EMPTY_PTR)
 | 
						|
  {
 | 
						|
    //            printf("DBG: Weirdness in releaseSegment.. tried to return a pointer with type %i (expected
 | 
						|
    //            %i)\n", (unsigned int)assignPtr->type, EMPTY_PTR );
 | 
						|
    assignPtr->type = EMPTY_PTR;
 | 
						|
    //            return ERR_FM_BAD_TYPE; // do not exit
 | 
						|
  }
 | 
						|
 | 
						|
  if (assignPtr->group != (uint64_t)segmentType)
 | 
						|
  {
 | 
						|
    //            printf("DBG: Weirdness in releaseSegment.. tried to return a pointer from group %i to group
 | 
						|
    //            %i\n", (unsigned int)assignPtr->group, segmentType );
 | 
						|
    return ERR_FM_RELEASE_ERR;
 | 
						|
  }
 | 
						|
 | 
						|
  // find the start of the chain
 | 
						|
  if (segmentType == ENTRY_32)
 | 
						|
  {
 | 
						|
    rc = releaseSubblock(cb, blockZero, freemgr_type, assignPtr);
 | 
						|
 | 
						|
    if (rc != NO_ERROR)
 | 
						|
    {
 | 
						|
      //                    printf("DBG: Error releasing sb\n");
 | 
						|
    }
 | 
						|
 | 
						|
    return rc;
 | 
						|
  }
 | 
						|
 | 
						|
  listOffset = calcPtrOffset(segmentType);
 | 
						|
 | 
						|
  if (freemgr_type == LIST && !(segmentType == ENTRY_4 || segmentType == ENTRY_BLK))
 | 
						|
  {
 | 
						|
    printf("DBG: Assign segment size illegal %i\n", (unsigned int)segmentType);
 | 
						|
    return ERR_INVALID_PARAM;  // should not have got here so quit with error
 | 
						|
  }
 | 
						|
 | 
						|
  getSubBlockEntry(blockZero, 0, listOffset, 8, &emptyPtr);
 | 
						|
 | 
						|
  /*       if (emptyPtr.fbo > numBlocks)
 | 
						|
         {
 | 
						|
         if( isDebug( DEBUG_1 )) { printf("DBG: Weirdness in releaseSegment.. emptyPtr.fbo > numBlocks (%llu
 | 
						|
     %llu)\n", emptyPtr.fbo, numBlocks );} return ERR_FM_BAD_FBO;
 | 
						|
         }*/
 | 
						|
 | 
						|
  // sub block is full or chain never started
 | 
						|
  if (emptyPtr.entry == ENTRY_PER_SUBBLOCK - 1 || emptyPtr.fbo == 0)
 | 
						|
  {
 | 
						|
    if (isDebug(DEBUG_3))
 | 
						|
    {
 | 
						|
      printf("DBG: No room in chain %i - need to add a sub-block\n", (unsigned int)segmentType);
 | 
						|
    }
 | 
						|
 | 
						|
    if (isDebug(DEBUG_2))
 | 
						|
    {
 | 
						|
      cout << "DBG: Empty ptr fbo " << emptyPtr.fbo << " sbid " << emptyPtr.sbid << " entry "
 | 
						|
           << emptyPtr.entry << "\n";
 | 
						|
    }
 | 
						|
 | 
						|
    // ask for a new sb to extend chain
 | 
						|
    rc = assignSubblock(cb, blockZero, freemgr_type, &newSb);
 | 
						|
 | 
						|
    if (rc != NO_ERROR)
 | 
						|
    {
 | 
						|
      printf("DBG: Error extending chain\n");
 | 
						|
      return rc;
 | 
						|
    }
 | 
						|
 | 
						|
    if (isDebug(DEBUG_2))
 | 
						|
    {
 | 
						|
      cout << "DBG: release segment, new SB is fbo " << newSb.fbo << " sbid " << newSb.sbid << " entry "
 | 
						|
           << newSb.entry << "\n";
 | 
						|
    }
 | 
						|
 | 
						|
    rc = readDBFile(cb, extraBlock.data, newSb.fbo);
 | 
						|
 | 
						|
    if (rc != NO_ERROR)
 | 
						|
    {
 | 
						|
      if (isDebug(DEBUG_1))
 | 
						|
      {
 | 
						|
        printf("DBG: File error during releaseSegment (3)\n");
 | 
						|
      }
 | 
						|
 | 
						|
      return rc;
 | 
						|
    }
 | 
						|
 | 
						|
    emptyPtr.type = EMPTY_LIST;  // writing into the LLP field so set type accordingly
 | 
						|
    setSubBlockEntry(extraBlock.data, newSb.sbid, 0, 8, &emptyPtr);
 | 
						|
    setSubBlockEntry(extraBlock.data, newSb.sbid, 1, 8, assignPtr);
 | 
						|
    rc = writeDBFile(cb, &extraBlock, newSb.fbo);
 | 
						|
 | 
						|
    if (rc != NO_ERROR)
 | 
						|
    {
 | 
						|
      if (isDebug(DEBUG_1))
 | 
						|
      {
 | 
						|
        printf("DBG: File error during releaseSegment (4)\n");
 | 
						|
      }
 | 
						|
 | 
						|
      return rc;
 | 
						|
    }
 | 
						|
 | 
						|
    newSb.entry = 1;
 | 
						|
    newSb.type = EMPTY_LIST;
 | 
						|
    newSb.group = segmentType;
 | 
						|
 | 
						|
    setSubBlockEntry(blockZero, 0, listOffset, 8, &newSb);
 | 
						|
    blockZero->dirty = 1;
 | 
						|
 | 
						|
    uint64_t count;
 | 
						|
    getSubBlockEntry(blockZero, 0, calcStatOffset(segmentType), 8, &count);
 | 
						|
    count++;
 | 
						|
    setSubBlockEntry(blockZero, 0, calcStatOffset(segmentType), 8, &count);
 | 
						|
 | 
						|
    return NO_ERROR;
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    //
 | 
						|
    emptyPtr.entry++;
 | 
						|
    rc = readDBFile(cb, workBlock.data, emptyPtr.fbo);
 | 
						|
 | 
						|
    if (rc != NO_ERROR)
 | 
						|
    {
 | 
						|
      if (isDebug(DEBUG_1))
 | 
						|
      {
 | 
						|
        printf("DBG: File error during releaseSegment\n");
 | 
						|
      }
 | 
						|
 | 
						|
      return rc;
 | 
						|
    }
 | 
						|
 | 
						|
    if (isDebug(DEBUG_2))
 | 
						|
    {
 | 
						|
      cout << "DBG: Empty map ENTRY_" << (1 << segmentType) << " is fbo " << emptyPtr.fbo << " sbid "
 | 
						|
           << emptyPtr.sbid << " entry " << emptyPtr.entry << "\n";
 | 
						|
    }
 | 
						|
 | 
						|
    setSubBlockEntry(workBlock.data, emptyPtr.sbid, emptyPtr.entry, 8, assignPtr);
 | 
						|
    rc = writeDBFile(cb, workBlock.data, emptyPtr.fbo);
 | 
						|
 | 
						|
    if (rc != NO_ERROR)
 | 
						|
    {
 | 
						|
      return rc;
 | 
						|
    }
 | 
						|
 | 
						|
    emptyPtr.type = EMPTY_LIST;
 | 
						|
    emptyPtr.group = segmentType;
 | 
						|
 | 
						|
    setSubBlockEntry(blockZero, 0, listOffset, 8, &emptyPtr);
 | 
						|
    blockZero->dirty = 1;  // sub block is full or chain never started
 | 
						|
  }
 | 
						|
 | 
						|
  uint64_t count;
 | 
						|
  getSubBlockEntry(blockZero, 0, calcStatOffset(segmentType), 8, &count);
 | 
						|
  count++;
 | 
						|
  setSubBlockEntry(blockZero, 0, calcStatOffset(segmentType), 8, &count);
 | 
						|
 | 
						|
  return NO_ERROR;
 | 
						|
}
 | 
						|
 | 
						|
const int FreeMgr::releaseSubblock(CommBlock& cb, DataBlock* blockZero, const int freemgr_type,
 | 
						|
                                   IdxEmptyListEntry* assignPtr)
 | 
						|
{
 | 
						|
  int rc;  // return code from file ops
 | 
						|
  DataBlock workBlock;
 | 
						|
  DataBlock extraBlock;
 | 
						|
  int listOffset;  // entry in block zero of head pointer
 | 
						|
  IdxEmptyListEntry emptyPtr, emptyMap;
 | 
						|
  uint64_t numBlocks;
 | 
						|
  FILE* indexFile;
 | 
						|
 | 
						|
  indexFile = cb.file.pFile;
 | 
						|
  /**
 | 
						|
   * Release sub-block - handle de-allocation of only sub-blocks
 | 
						|
   * This makes the assign/release code for smaller segments simpler and
 | 
						|
   * separates the tasks of handling the list containers and the list contents
 | 
						|
   * When called, we look at the bucket indicated as head of chain and if it full
 | 
						|
   * or not present (no room left in chain) then insert the returned SB as a bucket and
 | 
						|
   * move the head pointer
 | 
						|
   **/
 | 
						|
 | 
						|
  // if( isDebug( DEBUG_1 )) { printf("DBG: releaseSubblock\n"); }
 | 
						|
  if (isDebug(DEBUG_2))
 | 
						|
  {
 | 
						|
    cout << "DBG: releasing sb fbo " << assignPtr->fbo << " sbid " << assignPtr->sbid << " entry "
 | 
						|
         << assignPtr->entry << " from " << ((freemgr_type == LIST) ? "LIST" : "TREE") << " (type is "
 | 
						|
         << ((assignPtr->type == EMPTY_PTR) ? "EMPTY_PTR" : "Not EMPTY_PTR") << ")\n";
 | 
						|
  }
 | 
						|
 | 
						|
  if (!assignPtr)
 | 
						|
  {
 | 
						|
    //            printf ("DBG: Bad pointer: assignPtr is zero\n");
 | 
						|
    return ERR_INVALID_PARAM;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!blockZero)
 | 
						|
  {
 | 
						|
    printf("DBG: Bad pointer: pointer for blockZero is zero\n");
 | 
						|
    return ERR_INVALID_PARAM;
 | 
						|
  }
 | 
						|
 | 
						|
  numBlocks = getFileSize(indexFile) / BYTE_PER_BLOCK;
 | 
						|
 | 
						|
  /*       if (assignPtr->fbo > numBlocks)
 | 
						|
         {
 | 
						|
         if( isDebug( DEBUG_1 )) { printf("DBG: Weirdness in releaseSubblock.. assignPtr.fbo > numBlocks (%llu
 | 
						|
     %llu)\n", assignPtr->fbo, numBlocks );} return ERR_FM_BAD_FBO;
 | 
						|
         }*/
 | 
						|
  if (assignPtr->type != EMPTY_PTR)
 | 
						|
  {
 | 
						|
    printf("DBG: Weirdness in releaseSubblock.. tried to return a pointer with type %i (expected %i)\n",
 | 
						|
           (unsigned int)assignPtr->type, EMPTY_PTR);
 | 
						|
    return ERR_FM_BAD_TYPE;
 | 
						|
  }
 | 
						|
 | 
						|
  if (assignPtr->group != ENTRY_32)
 | 
						|
  {
 | 
						|
    printf("DBG: Weirdness in releaseSubblock.. tried to return a pointer from group %i to subblock group\n",
 | 
						|
           (unsigned int)assignPtr->group);
 | 
						|
    return ERR_INVALID_PARAM;
 | 
						|
  }
 | 
						|
 | 
						|
  // find the start of the chain
 | 
						|
  listOffset = calcPtrOffset(ENTRY_32);
 | 
						|
 | 
						|
  getSubBlockEntry(blockZero, 0, listOffset, 8, &emptyPtr);
 | 
						|
 | 
						|
  if (isDebug(DEBUG_2))
 | 
						|
  {
 | 
						|
    cout << "DBG: EM (sb release 1) sb fbo " << emptyPtr.fbo << " sbid " << emptyPtr.sbid << " entry "
 | 
						|
         << emptyPtr.entry << "\n";
 | 
						|
  }
 | 
						|
 | 
						|
  // sub block is full or chain empty
 | 
						|
  if (emptyPtr.entry == ENTRY_PER_SUBBLOCK - 1 || emptyPtr.fbo == 0)
 | 
						|
  {
 | 
						|
    // change type from EMPTY_PTR to EMPTY_LIST
 | 
						|
    assignPtr->type = EMPTY_LIST;
 | 
						|
 | 
						|
    // if( isDebug( DEBUG_1 )) { printf("DBG: No room in subblock chain - need to add a sub-block\n");  }
 | 
						|
    if (isDebug(DEBUG_2))
 | 
						|
    {
 | 
						|
      cout << "DBG: Change head pointer to fbo " << assignPtr->fbo << " sbid " << assignPtr->sbid << " entry "
 | 
						|
           << assignPtr->entry << "\n";
 | 
						|
    }
 | 
						|
 | 
						|
    // change head pointer to released segment
 | 
						|
    setSubBlockEntry(blockZero, 0, listOffset, 8, assignPtr);
 | 
						|
    blockZero->dirty = 1;
 | 
						|
 | 
						|
    // read in released segment to set llp of new block to point to current head of chain
 | 
						|
    rc = readDBFile(cb, extraBlock.data, assignPtr->fbo);
 | 
						|
 | 
						|
    if (rc != NO_ERROR)
 | 
						|
    {
 | 
						|
      if (isDebug(DEBUG_1))
 | 
						|
      {
 | 
						|
        cout << "DBG: File error during releaseSegment (2), rc: " << rc << " fbo/lbid: " << assignPtr->fbo
 | 
						|
             << "\n";
 | 
						|
      }
 | 
						|
 | 
						|
      return rc;
 | 
						|
    }
 | 
						|
 | 
						|
    if (isDebug(DEBUG_2))
 | 
						|
    {
 | 
						|
      cout << "DBG: Set LLP for fbo " << assignPtr->fbo << " sbid " << assignPtr->sbid << " entry "
 | 
						|
           << assignPtr->entry << "to fbo " << emptyPtr.fbo << " sbid " << emptyPtr.sbid << " entry "
 | 
						|
           << emptyPtr.entry << "\n";
 | 
						|
    }
 | 
						|
 | 
						|
    if (isDebug(DEBUG_3))
 | 
						|
    {
 | 
						|
      printf("Before\n");
 | 
						|
      printMemSubBlock(&extraBlock, assignPtr->sbid);
 | 
						|
    }
 | 
						|
 | 
						|
    emptyPtr.type = EMPTY_LIST;
 | 
						|
    // memset( extraBlock.data, 0, BYTE_PER_SUBBLOCK);
 | 
						|
    setSubBlockEntry(extraBlock.data, assignPtr->sbid, 0, 8, &emptyPtr);
 | 
						|
    rc = writeDBFile(cb, &extraBlock, assignPtr->fbo);
 | 
						|
 | 
						|
    if (rc != NO_ERROR)
 | 
						|
    {
 | 
						|
      return rc;
 | 
						|
    }
 | 
						|
 | 
						|
    if (isDebug(DEBUG_2))
 | 
						|
    {
 | 
						|
      getSubBlockEntry(blockZero, 0, listOffset, 8, &emptyMap);
 | 
						|
      cout << "DBG: EM (sb release 2) sb fbo " << emptyMap.fbo << " sbid " << emptyMap.sbid << " entry "
 | 
						|
           << emptyMap.entry << "\n";
 | 
						|
    }
 | 
						|
 | 
						|
    if (isDebug(DEBUG_3))
 | 
						|
    {
 | 
						|
      printf("After\n");
 | 
						|
      printMemSubBlock(&extraBlock, assignPtr->sbid);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    //
 | 
						|
    emptyPtr.entry++;
 | 
						|
    rc = readDBFile(cb, workBlock.data, emptyPtr.fbo);
 | 
						|
 | 
						|
    if (rc != NO_ERROR)
 | 
						|
    {
 | 
						|
      if (isDebug(DEBUG_1))
 | 
						|
      {
 | 
						|
        printf("DBG: File error during releaseSubblock\n");
 | 
						|
      }
 | 
						|
 | 
						|
      return rc;
 | 
						|
    }
 | 
						|
 | 
						|
    if (isDebug(DEBUG_3))
 | 
						|
    {
 | 
						|
      printf("Before\n");
 | 
						|
      printMemSubBlock(&workBlock, emptyPtr.sbid);
 | 
						|
    }
 | 
						|
 | 
						|
    setSubBlockEntry(workBlock.data, emptyPtr.sbid, emptyPtr.entry, 8, assignPtr);
 | 
						|
    rc = writeDBFile(cb, &workBlock, emptyPtr.fbo);
 | 
						|
 | 
						|
    if (rc != NO_ERROR)
 | 
						|
    {
 | 
						|
      return rc;
 | 
						|
    }
 | 
						|
 | 
						|
    if (isDebug(DEBUG_2))
 | 
						|
    {
 | 
						|
      cout << "DBG: setting emptyPtr sb fbo " << emptyPtr.fbo << " sbid " << emptyPtr.sbid << " entry "
 | 
						|
           << emptyPtr.entry << "\n";
 | 
						|
    }
 | 
						|
 | 
						|
    if (isDebug(DEBUG_3))
 | 
						|
    {
 | 
						|
      printf("After\n");
 | 
						|
      printMemSubBlock(&workBlock, emptyPtr.sbid);
 | 
						|
    }
 | 
						|
 | 
						|
    emptyPtr.type = EMPTY_LIST;
 | 
						|
    emptyPtr.group = ENTRY_32;
 | 
						|
 | 
						|
    setSubBlockEntry(blockZero, 0, listOffset, 8, &emptyPtr);
 | 
						|
    blockZero->dirty = 1;
 | 
						|
  }
 | 
						|
 | 
						|
  uint64_t count;
 | 
						|
 | 
						|
  getSubBlockEntry(blockZero, 0, calcStatOffset(ENTRY_32), 8, &count);
 | 
						|
  count++;
 | 
						|
  setSubBlockEntry(blockZero, 0, calcStatOffset(ENTRY_32), 8, &count);
 | 
						|
 | 
						|
  return NO_ERROR;
 | 
						|
}
 | 
						|
 | 
						|
const void FreeMgr::nullPtr(WriteEngine::IdxEmptyListEntry* assignPtr) const
 | 
						|
{
 | 
						|
  assignPtr->fbo = 0;
 | 
						|
  assignPtr->sbid = 0;
 | 
						|
  assignPtr->entry = 0;
 | 
						|
  assignPtr->type = 0;
 | 
						|
  assignPtr->group = 0;
 | 
						|
  assignPtr->spare = 0;
 | 
						|
  assignPtr->spare2 = 0;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * extendFreeSpace - Having reached the end of the available freespace or exhausted the block/subblock chain
 | 
						|
 * add extra space by extending the file and calling the Init function for the new space
 | 
						|
 *
 | 
						|
 * @param indexFile
 | 
						|
 * @param blockZero
 | 
						|
 * @param freemgrType
 | 
						|
 * @return
 | 
						|
 */
 | 
						|
const int FreeMgr::extendFreespace(CommBlock& cb, DataBlock* blockZero, int freemgrType)
 | 
						|
{
 | 
						|
  DataBlock workBlock;
 | 
						|
  int rc = NO_ERROR;  // result code from file ops
 | 
						|
  FILE* indexFile;
 | 
						|
  int allocSize = 0;
 | 
						|
 | 
						|
  indexFile = cb.file.pFile;
 | 
						|
 | 
						|
  if (isDebug(DEBUG_1))
 | 
						|
  {
 | 
						|
    printf("Extending File\n");
 | 
						|
  }
 | 
						|
 | 
						|
  int numBlocks = 1024;  // default number - should ask BRM for extentsize
 | 
						|
  int currSize = getFileSize(indexFile) / BYTE_PER_BLOCK;
 | 
						|
 | 
						|
  if (!allowExtend)
 | 
						|
  {
 | 
						|
    if (isDebug(DEBUG_1))
 | 
						|
    {
 | 
						|
      printf("DBG: Extension denied\n");
 | 
						|
    }
 | 
						|
 | 
						|
    return ERR_FM_EXTEND;
 | 
						|
  }
 | 
						|
 | 
						|
  if (isDebug(DEBUG_1))
 | 
						|
  {
 | 
						|
    printf("DBG: Extending free space in file\n");
 | 
						|
  }
 | 
						|
 | 
						|
  if (isDebug(DEBUG_1))
 | 
						|
  {
 | 
						|
    printf("DBG: File is currently: %i blocks   Asking for: %i blocks\n", currSize, numBlocks);
 | 
						|
  }
 | 
						|
 | 
						|
#ifdef BROKEN_BY_MULTIPLE_FILES_PER_OID
 | 
						|
  rc = extendFile(indexFile, cb.file.oid, numBlocks, allocSize, 0, 8, false);
 | 
						|
#endif
 | 
						|
 | 
						|
  if (rc != NO_ERROR)
 | 
						|
  {
 | 
						|
    return rc;
 | 
						|
  }
 | 
						|
 | 
						|
  if (isDebug(DEBUG_1))
 | 
						|
  {
 | 
						|
    printf("DBG: Extended file by %i blocks\n", allocSize);
 | 
						|
  }
 | 
						|
 | 
						|
  rc = init(cb, blockZero, freemgrType, ENTRY_32, currSize, 50);
 | 
						|
 | 
						|
  if (rc != NO_ERROR)
 | 
						|
  {
 | 
						|
    return rc;
 | 
						|
  }
 | 
						|
 | 
						|
  rc = init(cb, blockZero, freemgrType, ENTRY_BLK, currSize + 50, allocSize - 50);
 | 
						|
 | 
						|
  if (rc != NO_ERROR)
 | 
						|
  {
 | 
						|
    return rc;
 | 
						|
  }
 | 
						|
 | 
						|
  return NO_ERROR;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Quick utility function to map LBID if BRM in use, return original FBO otherwise
 | 
						|
 * @param cb
 | 
						|
 * @param fbo
 | 
						|
 * @return
 | 
						|
 */
 | 
						|
const uint64_t FreeMgr::mapLBID(CommBlock& cb, const uint64_t fbo, int& rc)
 | 
						|
{
 | 
						|
  uint64_t lbid = 0;
 | 
						|
 | 
						|
  rc = NO_ERROR;
 | 
						|
#ifdef BROKEN_BY_MULTIPLE_FILES_PER_OID
 | 
						|
  rc = BRMWrapper::getInstance()->getBrmInfo(cb.file.oid, fbo, lbid);
 | 
						|
#endif
 | 
						|
 | 
						|
  if (rc != NO_ERROR)
 | 
						|
  {
 | 
						|
    if (isDebug(DEBUG_0))
 | 
						|
    {
 | 
						|
      cout << "BRM Failure looking up lbid for oid: " << cb.file.oid << " fbo: " << fbo
 | 
						|
           << ", returning unchanged value\n";
 | 
						|
    }
 | 
						|
 | 
						|
    return fbo;
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    return lbid;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
const void FreeMgr::printMemSubBlock(DataBlock* curBlock, const int sbid)
 | 
						|
{
 | 
						|
  int off;
 | 
						|
  //      DataBlock         curBlock;
 | 
						|
  unsigned char* curPos;
 | 
						|
  IdxEmptyListEntry curEntry, testZero;
 | 
						|
 | 
						|
  nullPtr(&testZero);
 | 
						|
  //      readDBFile( m_pTreeFile, &curBlock, fbo );
 | 
						|
  curPos = curBlock->data + BYTE_PER_SUBBLOCK * sbid;
 | 
						|
  printf("\n======================== sbid: %i", sbid);
 | 
						|
 | 
						|
  for (int i = 0; i < ENTRY_PER_SUBBLOCK; i++)
 | 
						|
  {
 | 
						|
    memcpy(&curEntry, curPos, MAX_COLUMN_BOUNDARY);
 | 
						|
    off = memcmp(&testZero, &curEntry, MAX_COLUMN_BOUNDARY);
 | 
						|
    //         if( /*bNoZero &&*/ off == 0 )
 | 
						|
    //            continue;
 | 
						|
    printf("\n Entry %2d : ", i);
 | 
						|
 | 
						|
    for (int j = 0; j < MAX_COLUMN_BOUNDARY; j++)
 | 
						|
      printf(" %2X", *(curPos + j));
 | 
						|
 | 
						|
    cout << " fbo=" << curEntry.fbo << " sbid=" << curEntry.sbid << " entry=" << curEntry.entry
 | 
						|
         << " group=" << curEntry.group << " type=" << curEntry.type;
 | 
						|
 | 
						|
    curPos += MAX_COLUMN_BOUNDARY;
 | 
						|
  }
 | 
						|
 | 
						|
  printf("\n");
 | 
						|
}
 | 
						|
 | 
						|
}  // namespace WriteEngine
 |