/* 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_colbufmgrdctnry.cpp 4726 2013-08-07 03:38:36Z bwilkinson $ * ****************************************************************************/ #include "we_colbufmgr.h" #include "we_columninfo.h" #include "we_log.h" #include #include namespace WriteEngine { //------------------------------------------------------------------------------ // ColumnBufferManagerDctnry constructor that takes a ColumnInfo, colWidth, and // FILE*. //------------------------------------------------------------------------------ ColumnBufferManagerDctnry::ColumnBufferManagerDctnry( ColumnInfo* pColInfo, int colWidth, Log* logger, int compressionType) : ColumnBufferManager(pColInfo, colWidth, logger, compressionType) { } //------------------------------------------------------------------------------ // ColumnBufferManagerDctnry destructor. //------------------------------------------------------------------------------ ColumnBufferManagerDctnry::~ColumnBufferManagerDctnry() { } //------------------------------------------------------------------------------ // If we wanted to intercept the row data being written out by // ColumnBufferManagerDctnry in order to break up any buffer crossing an // extent boundary, this is where that logic would reside. However, for // dictionary columns we perform this extent division up front. So for a // dictionary column, this function is a simple pass-thru to the ColumnBuffer's // writeToFile() function. // The data to be written, starts at "startOffset" in the internal buffer and // is "writeSize" bytes long. //------------------------------------------------------------------------------ int ColumnBufferManagerDctnry::writeToFileExtentCheck( uint32_t startOffset, uint32_t writeSize) { if (fLog->isDebug( DEBUG_3 )) { std::ostringstream oss; oss << "Dctnry writeToFileExtentCheck" ": OID-" << fColInfo->curCol.dataFile.fid << "; DBRoot-" << fColInfo->curCol.dataFile.fDbRoot << "; part-" << fColInfo->curCol.dataFile.fPartition << "; seg-" << fColInfo->curCol.dataFile.fSegment << "; writeSize-" << writeSize << "; oldAvailFileSize-" << fColInfo->availFileSize << "; newAvailFileSize-" << (fColInfo->availFileSize - writeSize); fLog->logMsg( oss.str(), MSGLVL_INFO2 ); } int rc = fCBuf->writeToFile(startOffset, writeSize); if (rc != NO_ERROR) { WErrorCodes ec; std::ostringstream oss; oss << "writeToFileExtentCheck: write token extent failed: " << ec.errorString(rc); fLog->logMsg( oss.str(), rc, MSGLVL_ERROR ); return rc; } fColInfo->updateBytesWrittenCounts( writeSize ); return NO_ERROR; } //------------------------------------------------------------------------------ // Before a section is reserved to contain "nRows" of incoming data, this // function can be called to determine whether this group of rows will cause // the buffer to cross an extent boundary. If there is not room for "nRows", // the number of rows that will fit in the current extent are returned. // This function also catches and handles the case where an abbreviated // extent needs to be expanded to a full extent on disk. // // WARNING: If the extent is expanded, then this function will change the // information in the ColumnInfo struct that owns this // ColumnBufferManagerDctnry. //------------------------------------------------------------------------------ int ColumnBufferManagerDctnry::rowsExtentCheck( int nRows, int& nRows2 ) { nRows2 = nRows; int bufferSize = fCBuf->getSize(); long long spaceRequired = nRows * fColWidth; long dataInBuffer = 0; if (bufferSize > 0) dataInBuffer = (fBufFreeOffset - fBufWriteOffset + bufferSize) % bufferSize; // if extent is out of space, see if this is an abbrev extent we can expand if (((dataInBuffer + spaceRequired) > fColInfo->availFileSize) && (fColInfo->isAbbrevExtent())) { RETURN_ON_ERROR( fColInfo->expandAbbrevExtent(true) ) } if ((dataInBuffer + spaceRequired) > fColInfo->availFileSize) { spaceRequired = fColInfo->availFileSize - dataInBuffer; nRows2 = (int)(spaceRequired / fColWidth); if (fLog->isDebug( DEBUG_1 )) { std::ostringstream oss1; oss1 << "Dctnry rowsExtentCheck (filling extent): OID-" << fColInfo->curCol.dataFile.fid << "; DBRoot-" << fColInfo->curCol.dataFile.fDbRoot << "; part-" << fColInfo->curCol.dataFile.fPartition << "; seg-" << fColInfo->curCol.dataFile.fSegment << "; spaceRequired-" << spaceRequired << "; dataInBuffer-" << dataInBuffer << "; availSpace-" << fColInfo->availFileSize; fLog->logMsg( oss1.str(), MSGLVL_INFO2 ); std::ostringstream oss2; oss2 << "Dctnry rowsExtentCheck: OID-" << fColInfo->curCol.dataFile.fid << "; DBRoot-" << fColInfo->curCol.dataFile.fDbRoot << "; part-" << fColInfo->curCol.dataFile.fPartition << "; seg-" << fColInfo->curCol.dataFile.fSegment << "; Changing nRows from " << nRows << " to " << nRows2; fLog->logMsg( oss2.str(), MSGLVL_INFO2 ); } } else { if (fLog->isDebug( DEBUG_2 )) { std::ostringstream oss; oss << "Dctnry rowsExtentCheck: OID-" << fColInfo->curCol.dataFile.fid << "; DBRoot-" << fColInfo->curCol.dataFile.fDbRoot << "; part-" << fColInfo->curCol.dataFile.fPartition << "; seg-" << fColInfo->curCol.dataFile.fSegment << "; spaceRequired-" << spaceRequired << "; dataInBuffer-" << dataInBuffer << "; availSpace-" << fColInfo->availFileSize; fLog->logMsg( oss.str(), MSGLVL_INFO2 ); } } return NO_ERROR; } }