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 
			
		
		
		
	
		
			
				
	
	
		
			486 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			486 lines
		
	
	
		
			18 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_bulkrollbackfile.cpp 4737 2013-08-14 20:45:46Z bwilkinson $
 | |
| */
 | |
| 
 | |
| #include "we_bulkrollbackfile.h"
 | |
| #include "we_bulkrollbackmgr.h"
 | |
| 
 | |
| #include <sstream>
 | |
| 
 | |
| #include "we_define.h"
 | |
| #include "we_fileop.h"
 | |
| #include "messageids.h"
 | |
| #include "IDBDataFile.h"
 | |
| using namespace idbdatafile;
 | |
| 
 | |
| using namespace execplan;
 | |
| 
 | |
| namespace WriteEngine
 | |
| {
 | |
| 
 | |
| //------------------------------------------------------------------------------
 | |
| // BulkRollbackFile constructor
 | |
| //------------------------------------------------------------------------------
 | |
| BulkRollbackFile::BulkRollbackFile(BulkRollbackMgr* mgr) : fMgr(mgr)
 | |
| {
 | |
|     // Initialize empty dictionary header block used when reinitializing
 | |
|     // dictionary store extents.
 | |
|     const uint16_t freeSpace  = BYTE_PER_BLOCK -
 | |
|         (HDR_UNIT_SIZE + NEXT_PTR_BYTES + HDR_UNIT_SIZE + HDR_UNIT_SIZE);
 | |
|     const uint64_t nextPtr    = NOT_USED_PTR;
 | |
|     const uint16_t offSetZero = BYTE_PER_BLOCK;
 | |
|     const uint16_t endHeader  = DCTNRY_END_HEADER;
 | |
| 
 | |
|     memcpy(fDctnryHdr,                &freeSpace,  HDR_UNIT_SIZE);
 | |
|     memcpy(fDctnryHdr+ HDR_UNIT_SIZE, &nextPtr,   NEXT_PTR_BYTES);
 | |
|     memcpy(fDctnryHdr+ HDR_UNIT_SIZE + NEXT_PTR_BYTES,
 | |
|                                       &offSetZero, HDR_UNIT_SIZE);
 | |
|     memcpy(fDctnryHdr+ HDR_UNIT_SIZE + NEXT_PTR_BYTES + HDR_UNIT_SIZE,
 | |
|                                       &endHeader,  HDR_UNIT_SIZE);
 | |
| }
 | |
| 
 | |
| //------------------------------------------------------------------------------
 | |
| // BulkRollbackFile destructor
 | |
| //------------------------------------------------------------------------------
 | |
| BulkRollbackFile::~BulkRollbackFile()
 | |
| {
 | |
| }
 | |
| 
 | |
| //------------------------------------------------------------------------------
 | |
| // Build the specified database segment file name.
 | |
| //
 | |
| // columnOID      - OID of segment file to be found
 | |
| // fileTypeFlag   - true -> column file; false -> dictionary store file
 | |
| // dbRoot         - DBRoot of segment file to be found
 | |
| // partNum        - Partition number of segment file to be found
 | |
| // segNum         - Segment number of segment file to be found
 | |
| // segFileName (out)    - Name of segment file
 | |
| //------------------------------------------------------------------------------
 | |
| void BulkRollbackFile::buildSegmentFileName(
 | |
|     OID          columnOID,
 | |
|     bool         fileTypeFlag,
 | |
|     uint32_t    dbRoot,
 | |
|     uint32_t    partNum,
 | |
|     uint32_t    segNum,
 | |
|     std::string& segFileName )
 | |
| {
 | |
|     char fileName[FILE_NAME_SIZE];
 | |
|     int rc = fDbFile.getFileName( columnOID, fileName,
 | |
|         dbRoot, partNum, segNum );
 | |
|     if (rc != NO_ERROR)
 | |
|     {
 | |
|         WErrorCodes ec;
 | |
|         std::ostringstream oss;
 | |
|         oss << "Error constructing "    <<
 | |
|             (fileTypeFlag ? "column" : "dictionary store") <<
 | |
|             " filename for deletion"    <<
 | |
|             "; columnOID-" << columnOID <<
 | |
|             "; dbRoot-"    << dbRoot    <<
 | |
|             "; partNum-"   << partNum   <<
 | |
|             "; segNum-"    << segNum    <<
 | |
|             "; "           << ec.errorString(rc);
 | |
| 
 | |
|         throw WeException( oss.str(), rc );
 | |
|     }
 | |
| 
 | |
|     segFileName = fileName;
 | |
| }
 | |
| 
 | |
| //------------------------------------------------------------------------------
 | |
| // Delete the specified database segment file.
 | |
| //
 | |
| // columnOID      - OID of segment file to be deleted
 | |
| // fileTypeFlag   - true -> column file; false -> dictionary store file
 | |
| // dbRoot         - DBRoot of segment file to be deleted
 | |
| // partNum        - Partition number of segment file to be deleted
 | |
| // segNum         - Segment number of segment file to be deleted
 | |
| // segFileName    - Name of file to be deleted
 | |
| //------------------------------------------------------------------------------
 | |
| void BulkRollbackFile::deleteSegmentFile(
 | |
|     OID       columnOID, 
 | |
|     bool      fileTypeFlag,
 | |
|     uint32_t dbRoot,
 | |
|     uint32_t partNum, 
 | |
|     uint32_t segNum,
 | |
|     const std::string& segFileName )
 | |
| {
 | |
|     std::ostringstream msgText; 
 | |
|     msgText << "Deleting " << (fileTypeFlag ? "column" : "dictionary store") <<
 | |
|         " file: dbRoot-"   << dbRoot  <<
 | |
|         "; part#-"         << partNum <<
 | |
|         "; seg#-"          << segNum;
 | |
|     fMgr->logAMessage( logging::LOG_TYPE_INFO,
 | |
|         logging::M0075, columnOID, msgText.str() );
 | |
| 
 | |
|     // delete the db segment file if it exists
 | |
|     int rc = fDbFile.deleteFile( segFileName.c_str() );
 | |
|     if (rc != NO_ERROR)
 | |
|     {
 | |
|         if (rc != ERR_FILE_NOT_EXIST)
 | |
|         {
 | |
|             WErrorCodes ec;
 | |
|             std::ostringstream oss;
 | |
|             oss << "Error deleting segment file"
 | |
|                 "; columnOID-" << columnOID <<
 | |
|                 "; dbRoot-"    << dbRoot    <<
 | |
|                 "; partNum-"   << partNum   <<
 | |
|                 "; segNum-"    << segNum    <<
 | |
|                 "; "           << ec.errorString(rc);
 | |
| 
 | |
|             throw WeException( oss.str(), rc );
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| //------------------------------------------------------------------------------
 | |
| // Truncate the specified database segment file to the given file offset.
 | |
| //
 | |
| // columnOID      - OID of segment file to be truncated
 | |
| // dbRoot         - DBRoot of segment file to be truncated
 | |
| // partNum        - Partition number of segment file to be truncated
 | |
| // segNum         - Segment number of segment file to be truncated
 | |
| // fileSizeBlocks - Number of blocks to be left in the file.  Remainder of file
 | |
| //                  is to be truncated.
 | |
| //------------------------------------------------------------------------------
 | |
| void BulkRollbackFile::truncateSegmentFile(
 | |
|     OID       columnOID,
 | |
|     uint32_t dbRoot,
 | |
|     uint32_t partNum,
 | |
|     uint32_t segNum,
 | |
|     long long fileSizeBlocks )
 | |
| {
 | |
|     long long fileSizeBytes = fileSizeBlocks * BYTE_PER_BLOCK;
 | |
| 
 | |
|     std::ostringstream msgText;
 | |
|     msgText << "Truncating column file"
 | |
|         ": dbRoot-"          << dbRoot         <<
 | |
|         "; part#-"           << partNum        <<
 | |
|         "; seg#-"            << segNum         <<
 | |
|         "; totBlks-"         << fileSizeBlocks <<
 | |
|         "; fileSize(bytes)-" << fileSizeBytes;
 | |
|     fMgr->logAMessage( logging::LOG_TYPE_INFO,
 | |
|         logging::M0075, columnOID, msgText.str() );
 | |
| 
 | |
|     std::string segFile;
 | |
|     IDBDataFile* pFile = fDbFile.openFile(columnOID, dbRoot, partNum, segNum, segFile);
 | |
| 
 | |
|     if (pFile == 0)
 | |
|     {
 | |
|         std::ostringstream oss;
 | |
|         oss << "Error opening column segment file to rollback extents "
 | |
|             "from DB for"  <<
 | |
|             ": OID-"       << columnOID <<
 | |
|             "; DbRoot-"    << dbRoot    <<
 | |
|             "; partition-" << partNum   <<
 | |
|             "; segment-"   << segNum;
 | |
| 
 | |
|         throw WeException( oss.str(), ERR_FILE_OPEN );
 | |
|     }
 | |
| 
 | |
|     int rc = fDbFile.truncateFile( pFile, fileSizeBytes );
 | |
|     if (rc != NO_ERROR)
 | |
|     {
 | |
|         WErrorCodes ec;
 | |
|         std::ostringstream oss;
 | |
|         oss << "Error truncating column extents from DB for" <<
 | |
|             ": OID-"       << columnOID <<
 | |
|             "; DbRoot-"    << dbRoot    <<
 | |
|             "; partition-" << partNum   <<
 | |
|             "; segment-"   << segNum    <<
 | |
|             "; "           << ec.errorString(rc);
 | |
| 
 | |
|         fDbFile.closeFile( pFile );
 | |
|         throw WeException( oss.str(), rc );
 | |
|     }
 | |
| 
 | |
|     fDbFile.closeFile( pFile );
 | |
| }
 | |
| 
 | |
| //------------------------------------------------------------------------------
 | |
| // Reinitialize a column segment extent (in the db file) to empty values,
 | |
| // following the HWM.  Remaining extents in the file are truncated.
 | |
| //  
 | |
| // columnOID      - OID of segment file to be reinitialized
 | |
| // dbRoot         - DBRoot of segment file to be reinitialized
 | |
| // partNum        - Partition number of segment file to be reinitialized
 | |
| // segNum         - Segment number of segment file to be reinitialized
 | |
| // startOffsetBlk - File offset (after the HWM block), at which the file is
 | |
| //                  to be reinitialized.  Value is in blocks.
 | |
| // nBlocks        - Number of blocks to be reinitialized
 | |
| // colType        - Data type of the applicable column
 | |
| // colWidth       - Width in bytes, of the applicable column
 | |
| // restoreHwmChk  - Specifies whether HWM chunk is to be restored.  n/a for
 | |
| //                  uncompressed, but defined in this base class for the
 | |
| //                  compressed derived class.
 | |
| //------------------------------------------------------------------------------
 | |
| void BulkRollbackFile::reInitTruncColumnExtent(
 | |
|     OID         columnOID,
 | |
|     uint32_t    dbRoot,
 | |
|     uint32_t    partNum,
 | |
|     uint32_t    segNum,
 | |
|     long long   startOffsetBlk,
 | |
|     int         nBlocks,
 | |
|     CalpontSystemCatalog::ColDataType colType,
 | |
|     uint32_t  colWidth,
 | |
|     bool        /*restoreHwmChk*/ )
 | |
| {
 | |
|     long long startOffset = startOffsetBlk * BYTE_PER_BLOCK;
 | |
| 
 | |
|     std::ostringstream msgText;
 | |
|     msgText << "Reinit HWM column extent in db file"
 | |
|         ": dbRoot-"        << dbRoot      <<
 | |
|         "; part#-"         << partNum     <<
 | |
|         "; seg#-"          << segNum      <<
 | |
|         "; offset(bytes)-" << startOffset <<
 | |
|         "; freeBlks-"      << nBlocks;
 | |
|     fMgr->logAMessage( logging::LOG_TYPE_INFO,
 | |
|         logging::M0075, columnOID, msgText.str() );
 | |
| 
 | |
|     std::string segFile;
 | |
|     IDBDataFile* pFile = fDbFile.openFile(columnOID, dbRoot, partNum, segNum, segFile);
 | |
|     if (pFile == 0)
 | |
|     {
 | |
|         std::ostringstream oss;
 | |
|         oss << "Error opening HWM column segment file to rollback extents "
 | |
|             "from DB for"  << 
 | |
|             ": OID-"       << columnOID <<
 | |
|             "; DbRoot-"    << dbRoot    <<
 | |
|             "; partition-" << partNum   <<
 | |
|             "; segment-"   << segNum;
 | |
| 
 | |
|         throw WeException( oss.str(), ERR_FILE_OPEN );
 | |
|     }
 | |
| 
 | |
|     // nBlocks is based on full extents, but if the database file only has an
 | |
|     // abbreviated extent, then we reset nBlocks to reflect the size of the file
 | |
|     // (Only the 1st extent in part0, seg0 employs an abbreviated extent.)
 | |
| // DMC-SHARED_NOTHING_NOTE: Is it safe to assume only part0 seg0 is abbreviated?
 | |
|     if ((partNum == 0) && (segNum == 0))
 | |
|     {
 | |
|         long long nBytesInAbbrevExtent = INITIAL_EXTENT_ROWS_TO_DISK * colWidth;
 | |
|         if (startOffset <= nBytesInAbbrevExtent)
 | |
|         {
 | |
|             // This check would prevent us from truncating back to an
 | |
|             // abbreviated extent if the failed import expanded the initial
 | |
|             // extent; but when adding compression, decided to go ahead and
 | |
|             // truncate back to an abbreviated extent.
 | |
|             //long long fileSizeBytes;
 | |
|             //int rc = fDbFile.getFileSize2(pFile,fileSizeBytes);
 | |
|             //if (fileSizeBytes == nBytesInAbbrevExtent)
 | |
|             {
 | |
|                 nBlocks = (nBytesInAbbrevExtent-startOffset) / BYTE_PER_BLOCK;
 | |
| 
 | |
|                 std::ostringstream msgText2;
 | |
|                 msgText2 << "Reinit (abbrev) HWM column extent in db file"
 | |
|                     ": dbRoot-"        << dbRoot      <<
 | |
|                     "; part#-"         << partNum     <<
 | |
|                     "; seg#-"          << segNum      <<
 | |
|                     "; offset(bytes)-" << startOffset <<
 | |
|                     "; freeBlks-"      << nBlocks;
 | |
|                 fMgr->logAMessage( logging::LOG_TYPE_INFO,
 | |
|                     logging::M0075, columnOID, msgText2.str() );
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // Initialize the remainder of the extent after the HWM block
 | |
|     uint64_t emptyVal = fDbFile.getEmptyRowValue( colType, colWidth );
 | |
| 
 | |
|     int rc = fDbFile.reInitPartialColumnExtent( pFile,
 | |
|         startOffset,
 | |
|         nBlocks,
 | |
|         emptyVal,
 | |
|         colWidth );
 | |
|     if (rc != NO_ERROR)
 | |
|     {
 | |
|         WErrorCodes ec;
 | |
|         std::ostringstream oss;
 | |
|         oss << "Error rolling back HWM column extent from DB for" <<
 | |
|             ": OID-"       << columnOID <<
 | |
|             "; DbRoot-"    << dbRoot    <<
 | |
|             "; partition-" << partNum   <<
 | |
|             "; segment-"   << segNum    <<
 | |
|             "; "           << ec.errorString(rc);
 | |
| 
 | |
|         fDbFile.closeFile( pFile );
 | |
|         throw WeException( oss.str(), rc );
 | |
|     }
 | |
| 
 | |
|     // Truncate the remainder of the file
 | |
|     rc = fDbFile.truncateFile( pFile, pFile->tell() );
 | |
| 
 | |
|     if (rc != NO_ERROR)
 | |
|     {
 | |
|         WErrorCodes ec;
 | |
|         std::ostringstream oss;
 | |
|         oss << "Error truncating post-HWM column extents "
 | |
|             "from HWM segment DB file for" <<
 | |
|             ": OID-"       << columnOID <<
 | |
|             "; DbRoot-"    << dbRoot    <<
 | |
|             "; partition-" << partNum   <<
 | |
|             "; segment-"   << segNum    <<
 | |
|             "; "           << ec.errorString(rc);
 | |
| 
 | |
|         fDbFile.closeFile( pFile );
 | |
|         throw WeException( oss.str(), rc );
 | |
|     }
 | |
| 
 | |
|     fDbFile.closeFile( pFile );
 | |
| }
 | |
| 
 | |
| //------------------------------------------------------------------------------
 | |
| // Reinitialize a dictionary segment extent (in the db file) to empty blocks,
 | |
| // following the HWM.  Remaining extents in the file are truncated.
 | |
| //  
 | |
| // dStoreOID      - OID of segment store file to be reinitialized
 | |
| // dbRoot         - DBRoot of segment file to be reinitialized
 | |
| // partNum        - Partition number of segment file to be reinitialized
 | |
| // segNum         - Segment number of segment file to be reinitialized
 | |
| // startOffsetBlk - Starting block (after the HWM block), at which the file is
 | |
| //                  to be reinitialized.  Value is in raw data blocks.
 | |
| // nBlocks        - Number of blocks to be reinitialized
 | |
| //------------------------------------------------------------------------------
 | |
| void BulkRollbackFile::reInitTruncDctnryExtent(
 | |
|     OID         dStoreOID,
 | |
|     uint32_t   dbRoot,
 | |
|     uint32_t   partNum,
 | |
|     uint32_t   segNum,
 | |
|     long long   startOffsetBlk,
 | |
|     int         nBlocks )
 | |
| {
 | |
|     long long startOffset = startOffsetBlk * BYTE_PER_BLOCK;
 | |
| 
 | |
|     std::ostringstream msgText;
 | |
|     msgText << "Reinit dictionary store extent in db file"
 | |
|         ": dbRoot-"        << dbRoot      <<
 | |
|         "; part#-"         << partNum     <<
 | |
|         "; seg#-"          << segNum      <<
 | |
|         "; offset(bytes)-" << startOffset <<
 | |
|         "; numblks-"       << nBlocks;
 | |
|     fMgr->logAMessage( logging::LOG_TYPE_INFO,
 | |
|         logging::M0075, dStoreOID, msgText.str() );
 | |
| 
 | |
|     std::string segFile;
 | |
|     IDBDataFile* pFile = fDbFile.openFile(dStoreOID, dbRoot, partNum, segNum, segFile);
 | |
|     if (pFile == 0)
 | |
|     {
 | |
|         std::ostringstream oss;
 | |
|         oss << "Error opening dictionary store segment file to rollback extents"
 | |
|             " from DB for" <<
 | |
|             ": OID-"       << dStoreOID <<
 | |
|             "; DbRoot-"    << dbRoot    <<
 | |
|             "; partition-" << partNum   <<
 | |
|             "; segment-"   << segNum;
 | |
| 
 | |
|         throw WeException( oss.str(), ERR_FILE_OPEN );
 | |
|     }
 | |
| 
 | |
|     // nBlocks is based on full extents, but if the database file only has an
 | |
|     // abbreviated extent, then we reset nBlocks to reflect the size of the file
 | |
|     // (Unlike column files which only employ an abbreviated extent for the
 | |
|     // 1st extent in part0, seg0, all new store files start with abbrev extent)
 | |
|     const uint32_t PSEUDO_COL_WIDTH = 8; // simulated col width for dictionary
 | |
|     long long nBytesInAbbrevExtent = INITIAL_EXTENT_ROWS_TO_DISK *
 | |
|                                      PSEUDO_COL_WIDTH;
 | |
|     if (startOffset <= nBytesInAbbrevExtent)
 | |
|     {
 | |
|         // This check would prevent us from truncating back to an
 | |
|         // abbreviated extent if the failed import expanded the initial
 | |
|         // extent; but when adding compression, decided to go ahead and
 | |
|         // truncate back to an abbreviated extent.
 | |
|         //long long fileSizeBytes;
 | |
|         //int rc = fDbFile.getFileSize2(pFile,fileSizeBytes);
 | |
|         //if (fileSizeBytes == nBytesInAbbrevExtent)
 | |
|         {
 | |
|             nBlocks = (nBytesInAbbrevExtent-startOffset) / BYTE_PER_BLOCK;
 | |
| 
 | |
|             std::ostringstream msgText2;
 | |
|             msgText2 << "Reinit (abbrev) dictionary store extent in db file"
 | |
|                 ": dbRoot-"        << dbRoot      <<
 | |
|                 "; part#-"         << partNum     <<
 | |
|                 "; seg#-"          << segNum      <<
 | |
|                 "; offset(bytes)-" << startOffset <<
 | |
|                 "; numblks-"       << nBlocks;
 | |
|             fMgr->logAMessage( logging::LOG_TYPE_INFO,
 | |
|                 logging::M0075, dStoreOID, msgText2.str() );
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // Initialize the remainder of the extent after the HWM block
 | |
|     int rc = fDbFile.reInitPartialDctnryExtent( pFile,
 | |
|         startOffset,
 | |
|         nBlocks,
 | |
|         fDctnryHdr,
 | |
|         DCTNRY_HEADER_SIZE );
 | |
|     if (rc != NO_ERROR)
 | |
|     {
 | |
|         WErrorCodes ec;
 | |
|         std::ostringstream oss;
 | |
|         oss << "Error rolling back HWM dictionary store extent from DB for" <<
 | |
|             ": OID-"       << dStoreOID <<
 | |
|             "; DbRoot-"    << dbRoot    <<
 | |
|             "; partition-" << partNum   <<
 | |
|             "; segment-"   << segNum    <<
 | |
|             "; "           << ec.errorString(rc);
 | |
| 
 | |
|         fDbFile.closeFile( pFile );
 | |
|         throw WeException( oss.str(), rc );
 | |
|     }
 | |
| 
 | |
|     // Truncate the remainder of the file
 | |
|     rc = fDbFile.truncateFile( pFile, pFile->tell() );
 | |
| 
 | |
|     if (rc != NO_ERROR)
 | |
|     {
 | |
|         WErrorCodes ec;
 | |
|         std::ostringstream oss;
 | |
|         oss << "Error truncating post-HWM dictionary store extents "
 | |
|             "from DB file for"          <<
 | |
|             ": OID-"       << dStoreOID <<
 | |
|             "; DbRoot-"    << dbRoot    <<
 | |
|             "; partition-" << partNum   <<
 | |
|             "; segment-"   << segNum    <<
 | |
|             "; "           << ec.errorString(rc);
 | |
| 
 | |
|         fDbFile.closeFile( pFile );
 | |
|         throw WeException( oss.str(), rc );
 | |
|     }
 | |
| 
 | |
|     fDbFile.closeFile( pFile );
 | |
| }
 | |
| 
 | |
| //------------------------------------------------------------------------------
 | |
| // For uncompressed data...
 | |
| // Always return true, in order to always reInit the post-HWM blocks for the
 | |
| // HWM extent to empty values.
 | |
| // This function is defined as a stub, so that the derived compression
 | |
| // class can override this functionality, and return true or false depending
 | |
| // on whether the HWM chunk was modified and backed up to disk.
 | |
| //------------------------------------------------------------------------------
 | |
| bool BulkRollbackFile::doWeReInitExtent( OID columnOID,
 | |
|     uint32_t dbRoot,
 | |
|     uint32_t partNum,
 | |
|     uint32_t segNum) const
 | |
| {
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| } //end of namespace
 |