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 
			
		
		
		
	
		
			
				
	
	
		
			307 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			307 lines
		
	
	
		
			12 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_extentstripealloc.cpp 4450 2013-01-21 14:13:24Z rdempsey $
 | 
						||
 *
 | 
						||
 ******************************************************************************/
 | 
						||
 | 
						||
/** @file
 | 
						||
 * Contains class to allocate a "stripe" of extents for all columns across a tbl
 | 
						||
 */
 | 
						||
 | 
						||
#include "we_extentstripealloc.h"
 | 
						||
 | 
						||
#include <iostream>
 | 
						||
#include <sstream>
 | 
						||
 | 
						||
#include "we_define.h"
 | 
						||
#include "we_log.h"
 | 
						||
#include "we_brm.h"
 | 
						||
 | 
						||
namespace
 | 
						||
{
 | 
						||
typedef std::tr1::unordered_multimap<WriteEngine::OID,
 | 
						||
        WriteEngine::AllocExtEntry,
 | 
						||
        WriteEngine::AllocExtHasher> AllocExtMap;
 | 
						||
typedef AllocExtMap::iterator       AllocExtMapIter;
 | 
						||
typedef AllocExtMap::const_iterator ConstAllocExtMapIter;
 | 
						||
}
 | 
						||
 | 
						||
namespace WriteEngine
 | 
						||
{
 | 
						||
 | 
						||
//------------------------------------------------------------------------------
 | 
						||
// Constructor
 | 
						||
//------------------------------------------------------------------------------
 | 
						||
ExtentStripeAlloc::ExtentStripeAlloc( OID tableOID,
 | 
						||
                                      Log* logger ) : fTableOID(tableOID), fLog(logger), fStripeCount(0)
 | 
						||
{
 | 
						||
}
 | 
						||
 | 
						||
//------------------------------------------------------------------------------
 | 
						||
// Destructor
 | 
						||
// Note: fMap will automatically get cleared by unordered_map destructor,
 | 
						||
//       so no need to explicitly call clear() in "this" destructor.
 | 
						||
//------------------------------------------------------------------------------
 | 
						||
ExtentStripeAlloc::~ExtentStripeAlloc( )
 | 
						||
{
 | 
						||
}
 | 
						||
 | 
						||
//------------------------------------------------------------------------------
 | 
						||
// Add a column to be associated with the "stripe" allocations for "this"
 | 
						||
// ExtentStripeAlloc object.
 | 
						||
//------------------------------------------------------------------------------
 | 
						||
void ExtentStripeAlloc::addColumn( OID colOID, int colWidth )
 | 
						||
{
 | 
						||
    boost::mutex::scoped_lock lock(fMapMutex);
 | 
						||
 | 
						||
    fColOIDs.push_back  ( colOID   );
 | 
						||
    fColWidths.push_back( colWidth );
 | 
						||
}
 | 
						||
 | 
						||
//------------------------------------------------------------------------------
 | 
						||
// Allocate a "stripe" of column extents for the relevant table associated
 | 
						||
// with the specified column OID, and at the specified DBRoot.  The partition
 | 
						||
// number, segment number, etc associated with the allocated extent are
 | 
						||
// returned in the output arguments.
 | 
						||
//
 | 
						||
// Note that a multimap is used for the internal extent collection, with the
 | 
						||
// column OID as the key.  We would typically expect that we would not have
 | 
						||
// more than 1 extent entry for a given column OID in our map at the same
 | 
						||
// time.  If this were always true, then a map (and not a multimap) would
 | 
						||
// suffice.
 | 
						||
// However, I suppose that if the read buffer were large enough, and the
 | 
						||
// column widths small enough, then a parsing thread for a read buffer could
 | 
						||
// end up asking for a "stripe" of extents "before" all the allocated extents
 | 
						||
// for the previous read buffer have been used.  In this case, we may end
 | 
						||
// up needing to store more than 1 column extent for the same column, in
 | 
						||
// our internal collection.  Thus a multimap is used.  To handle this case,
 | 
						||
// we not only search the internal map for the specified column OID, but we
 | 
						||
// also:
 | 
						||
// 1. make sure we have an extent for the requested DBRoot
 | 
						||
// 2. select the lowest allocated stripe, if there should be more than
 | 
						||
//    one column extent with the same DBRoot.
 | 
						||
//------------------------------------------------------------------------------
 | 
						||
int ExtentStripeAlloc::allocateExtent( OID oid,
 | 
						||
                                       uint16_t     dbRoot,
 | 
						||
                                       uint32_t&    partNum, // used as input for empty DBRoot, else output only
 | 
						||
                                       uint16_t&    segNum,
 | 
						||
                                       BRM::LBID_t& startLbid,
 | 
						||
                                       int&         allocSize,
 | 
						||
                                       HWM&         hwm,
 | 
						||
                                       std::string& errMsg )
 | 
						||
{
 | 
						||
    int retStatus = NO_ERROR;
 | 
						||
    bool bFound   = false;
 | 
						||
    AllocExtMapIter extentEntryIter;
 | 
						||
    errMsg.clear();
 | 
						||
 | 
						||
    std::pair<AllocExtMapIter, AllocExtMapIter> iters;
 | 
						||
 | 
						||
    boost::mutex::scoped_lock lock(fMapMutex);
 | 
						||
 | 
						||
    // Search for an extent matching the requested OID and DBRoot.
 | 
						||
    // We also filter by selecting the lowest stripe number.  See
 | 
						||
    // function description that precedes this function for more detail.
 | 
						||
    iters = fMap.equal_range( oid );
 | 
						||
 | 
						||
    if (iters.first != iters.second)
 | 
						||
    {
 | 
						||
        for (AllocExtMapIter it = iters.first; it != iters.second; ++it)
 | 
						||
        {
 | 
						||
            if (it->second.fDbRoot == dbRoot)
 | 
						||
            {
 | 
						||
                if ((!bFound) ||
 | 
						||
                        (it->second.fStripeKey <
 | 
						||
                         extentEntryIter->second.fStripeKey))
 | 
						||
                {
 | 
						||
                    extentEntryIter = it;
 | 
						||
                }
 | 
						||
 | 
						||
                bFound = true;
 | 
						||
            }
 | 
						||
        }
 | 
						||
    }
 | 
						||
 | 
						||
    // Return selected extent
 | 
						||
    if (bFound)
 | 
						||
    {
 | 
						||
        partNum   = extentEntryIter->second.fPartNum;
 | 
						||
        segNum    = extentEntryIter->second.fSegNum;
 | 
						||
        startLbid = extentEntryIter->second.fStartLbid;
 | 
						||
        allocSize = extentEntryIter->second.fAllocSize;
 | 
						||
        hwm       = extentEntryIter->second.fHwm;
 | 
						||
        errMsg    = extentEntryIter->second.fStatusMsg;
 | 
						||
        retStatus = extentEntryIter->second.fStatus;
 | 
						||
 | 
						||
        fMap.erase( extentEntryIter );
 | 
						||
    }
 | 
						||
    else // Allocate "stripe" of extents if there's no entry for this column OID
 | 
						||
    {
 | 
						||
        fStripeCount++;
 | 
						||
 | 
						||
        std::ostringstream oss1;
 | 
						||
        oss1 << "Allocating next stripe(" << fStripeCount <<
 | 
						||
             ") of column extents for table " << fTableOID <<
 | 
						||
             "; DBRoot-" << dbRoot;
 | 
						||
        fLog->logMsg( oss1.str(), MSGLVL_INFO2 );
 | 
						||
 | 
						||
        std::vector<BRM::CreateStripeColumnExtentsArgIn>  cols;
 | 
						||
        std::vector<BRM::CreateStripeColumnExtentsArgOut> extents;
 | 
						||
 | 
						||
        for (unsigned int j = 0; j < fColOIDs.size(); ++j)
 | 
						||
        {
 | 
						||
            BRM::CreateStripeColumnExtentsArgIn colEntry;
 | 
						||
            colEntry.oid   = fColOIDs[j];
 | 
						||
            colEntry.width = fColWidths[j];
 | 
						||
            cols.push_back( colEntry );
 | 
						||
        }
 | 
						||
 | 
						||
        uint32_t    allocPartNum   = partNum;
 | 
						||
        uint16_t    allocSegNum    = 0;
 | 
						||
        BRM::LBID_t allocStartLbid = 0;
 | 
						||
        int         allocAllocSize = 0;
 | 
						||
        HWM         allocHwm       = 0;
 | 
						||
        int         allocStatus    = NO_ERROR;
 | 
						||
        std::string allocStatusMsg;
 | 
						||
 | 
						||
        int rc = BRMWrapper::getInstance()->allocateStripeColExtents(
 | 
						||
                     cols, dbRoot, allocPartNum, allocSegNum, extents );
 | 
						||
 | 
						||
        // If allocation error occurs, we go ahead and store extent entries
 | 
						||
        // with error status, to satisfy subsequent allocations in same stripe.
 | 
						||
        if (rc != NO_ERROR)
 | 
						||
        {
 | 
						||
            for (unsigned int i = 0; i < fColOIDs.size(); ++i)
 | 
						||
            {
 | 
						||
                if (oid != fColOIDs[i])
 | 
						||
                {
 | 
						||
                    allocStatus = rc;
 | 
						||
 | 
						||
                    std::ostringstream oss;
 | 
						||
                    oss << "Previous error allocating extent stripe for "
 | 
						||
                        "table " << fTableOID << "; DBRoot: " << dbRoot;
 | 
						||
                    allocStatusMsg = oss.str();
 | 
						||
 | 
						||
                    // For error case, just store 0 for part#,segnum, etc.
 | 
						||
                    AllocExtEntry extentEntry(fColOIDs[i], fColWidths[i],
 | 
						||
                                              dbRoot, 0, 0, 0, 0, 0,
 | 
						||
                                              allocStatus, allocStatusMsg, fStripeCount );
 | 
						||
 | 
						||
                    fMap.insert( AllocExtMap::value_type(fColOIDs[i],
 | 
						||
                                                         extentEntry) );
 | 
						||
                }
 | 
						||
            }
 | 
						||
 | 
						||
            std::ostringstream oss;
 | 
						||
            oss << "Error allocating extent stripe for "
 | 
						||
                "table " << fTableOID << "; DBRoot: " << dbRoot;
 | 
						||
            errMsg = oss.str();
 | 
						||
 | 
						||
            return rc;
 | 
						||
        }
 | 
						||
 | 
						||
        // Save allocated extents into fMap for later use.  For the OID
 | 
						||
        // requested by this function call, we just return the extent info.
 | 
						||
        for (unsigned int i = 0; i < fColOIDs.size(); ++i)
 | 
						||
        {
 | 
						||
            allocStartLbid = extents[i].startLbid;
 | 
						||
            allocAllocSize = extents[i].allocSize;
 | 
						||
            allocHwm       = extents[i].startBlkOffset;
 | 
						||
 | 
						||
            // Might consider controlling this with debug, but we always
 | 
						||
            // log out for now.
 | 
						||
            //if (fLog->isDebug( DEBUG_1 ))
 | 
						||
            {
 | 
						||
                std::ostringstream oss;
 | 
						||
                oss << "Stripe Allocation: OID-"  << fColOIDs[i] <<
 | 
						||
                    "; DBRoot-" << dbRoot         <<
 | 
						||
                    "; Part#-"  << allocPartNum   <<
 | 
						||
                    "; Seg#-"   << allocSegNum    <<
 | 
						||
                    "; lbid-"   << allocStartLbid <<
 | 
						||
                    "; fbo-"    << allocHwm       <<
 | 
						||
                    "; nblks-"  << allocAllocSize;
 | 
						||
                fLog->logMsg( oss.str(), MSGLVL_INFO2 );
 | 
						||
            }
 | 
						||
 | 
						||
            // Assign output args for requested column OID
 | 
						||
            if (oid == fColOIDs[i])
 | 
						||
            {
 | 
						||
                partNum   = allocPartNum;
 | 
						||
                segNum    = allocSegNum;
 | 
						||
                startLbid = allocStartLbid;
 | 
						||
                allocSize = allocAllocSize;
 | 
						||
                hwm       = allocHwm;
 | 
						||
            }
 | 
						||
            else // Add all extents in "stripe" (other than requested column)
 | 
						||
            {
 | 
						||
                // to the collection of extents
 | 
						||
                AllocExtEntry extentEntry(fColOIDs[i], fColWidths[i],
 | 
						||
                                          dbRoot, allocPartNum, allocSegNum,
 | 
						||
                                          allocStartLbid, allocAllocSize, allocHwm,
 | 
						||
                                          allocStatus, allocStatusMsg, fStripeCount );
 | 
						||
 | 
						||
                fMap.insert( AllocExtMap::value_type(fColOIDs[i], extentEntry) );
 | 
						||
            }
 | 
						||
        }
 | 
						||
    }
 | 
						||
 | 
						||
    return retStatus;
 | 
						||
}
 | 
						||
 | 
						||
//------------------------------------------------------------------------------
 | 
						||
// Debug logging function to log contents of the allocated extents that are
 | 
						||
// pending.
 | 
						||
//------------------------------------------------------------------------------
 | 
						||
void ExtentStripeAlloc::print( )
 | 
						||
{
 | 
						||
    boost::mutex::scoped_lock lock(fMapMutex);
 | 
						||
 | 
						||
    std::ostringstream oss;
 | 
						||
    oss << "Current Pending Extents for table " << fTableOID << ":";
 | 
						||
 | 
						||
    if (fMap.size() > 0)
 | 
						||
    {
 | 
						||
        for (ConstAllocExtMapIter iter = fMap.begin();
 | 
						||
                iter != fMap.end();
 | 
						||
                ++iter)
 | 
						||
        {
 | 
						||
            oss << std::endl;
 | 
						||
            oss << "  oid: "    << iter->second.fOid       <<
 | 
						||
                "; wid: "    << iter->second.fColWidth  <<
 | 
						||
                "; root: "   << iter->second.fDbRoot    <<
 | 
						||
                "; part: "   << iter->second.fPartNum   <<
 | 
						||
                "; seg: "    << iter->second.fSegNum    <<
 | 
						||
                "; lbid: "   << iter->second.fStartLbid <<
 | 
						||
                "; size: "   << iter->second.fAllocSize <<
 | 
						||
                "; hwm: "    << iter->second.fHwm       <<
 | 
						||
                "; stripe: " << iter->second.fStripeKey <<
 | 
						||
                "; stat: "   << iter->second.fStatus    <<
 | 
						||
                "; msg: "    << iter->second.fStatusMsg;
 | 
						||
        }
 | 
						||
    }
 | 
						||
    else
 | 
						||
    {
 | 
						||
        oss << " <EMPTY>";
 | 
						||
    }
 | 
						||
 | 
						||
    fLog->logMsg( oss.str(), MSGLVL_INFO2 );
 | 
						||
}
 | 
						||
 | 
						||
} //end of namespace
 |