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 
			
		
		
		
	
		
			
				
	
	
		
			407 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			407 lines
		
	
	
		
			16 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
 | 
						|
  const uint8_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;
 | 
						|
}
 | 
						|
 | 
						|
}  // namespace WriteEngine
 |