You've already forked mariadb-columnstore-engine
							
							
				mirror of
				https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
				synced 2025-10-30 07:25:34 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			303 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			303 lines
		
	
	
		
			11 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
 |