1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2025-04-18 21:44:02 +03:00
Roman Nozdrin 5fce19df0a MCOL-4412 Introduce TypeHandler::getEmptyValueForType to return const ptr for an empty value
WE changes for SQL DML and DDL operations

Changes for bulk operations

Changes for scanning operations

Cleanup
2021-01-18 12:30:17 +00:00

495 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
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;
}
} //end of namespace