blob: 7ff61d78a4c47369c62cb89e06d7cee8e2c5a1b0 [file] [log] [blame]
/**********************************************************************
// @@@ START COPYRIGHT @@@
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
// @@@ END COPYRIGHT @@@
//
**********************************************************************/
/* -*-C++-*-
******************************************************************************
*
* File: RuDupElimTask.cpp
* Description: Implementation of class CRUDupElimTask
*
*
* Created: 12/29/1999
* Language: C++
*
*
*
******************************************************************************
*/
#include "RuDupElimTask.h"
#include "RuDupElimTaskExecutor.h"
#include "RuMV.h"
#include "RuTbl.h"
#include "RuEmpCheckVector.h"
#include "RuGlobals.h"
#include "RuOptions.h"
//--------------------------------------------------------------------------//
// Constructor and destructor of CRUDupElimTask
//--------------------------------------------------------------------------//
CRUDupElimTask::CRUDupElimTask(Lng32 id, CRUTbl &table) :
inherited(id, table),
isRangeResolv_(FALSE),
isSingleRowResolv_(FALSE),
isSkipCrossTypeResolution_(FALSE),
deLevel_(CRUDeltaDef::NO_DE),
beginEpoch_(0),
endEpoch_(0)
{}
CRUDupElimTask::~CRUDupElimTask() {}
//--------------------------------------------------------------------------//
// CRUDupElimTask::NeedToExecuteDE()
//--------------------------------------------------------------------------//
BOOL CRUDupElimTask::NeedToExecuteDE() const
{
return (TRUE == isRangeResolv_ || TRUE == isSingleRowResolv_);
}
//--------------------------------------------------------------------------//
// CRUDupElimTask::CreateExecutorInstance()
//
// Task executor's creation.
//
//--------------------------------------------------------------------------//
CRUTaskExecutor *CRUDupElimTask::CreateExecutorInstance()
{
// Setup the internal data structures ...
SetupDS();
// Create the executor itself
CRUTaskExecutor *pTaskEx = new CRUDupElimTaskExecutor(this);
return pTaskEx;
}
//--------------------------------------------------------------------------//
// CRUDupElimTask::PullDataFromExecutor()
//
// Refinement of the base class's method.
//
//--------------------------------------------------------------------------//
void CRUDupElimTask::PullDataFromExecutor()
{
if (FALSE == WasExecuted())
{
return; // Nothing to take from the executor
}
CRUTbl &tbl = GetTable();
CRUDupElimTaskExecutor &taskEx = (CRUDupElimTaskExecutor &)GetExecutor();
tbl.SetDELevel(GetDELevel());
// Copy the DE statistics to the table object
CRUDeltaStatisticsMap &statMap = tbl.GetStatisticsMap();
statMap = taskEx.GetStatisticsMap();
tbl.PropagateDEStatisticsToUsingMVs();
}
//--------------------------------------------------------------------------//
// CRUDupElimTask::GetDeltaStatisticsSize()
//
// Estimate the room for the delta statistics in the reply from the
// task process (this affects the size of the IPC buffer to allocate).
//
//--------------------------------------------------------------------------//
Lng32 CRUDupElimTask::GetDeltaStatisticsBufSize() const
{
CRUTbl &tbl = GetTable();
Int32 nStatEntries = tbl.GetIncrementalInvolvedMVsUsingMe().GetCount();
Int32 singleStatSize =
CRUDeltaStatistics::GetPackedBufferSize(tbl.GetUpdateBitmapSize());
return nStatEntries * singleStatSize;
}
//--------------------------------------------------------------------------//
// PRIVATE AREA
//--------------------------------------------------------------------------//
//--------------------------------------------------------------------------//
// CRUDupElimTask::SetupDS()
//
// CreateExecutorInstance() callee.
//
// Setup the internal data structures before the executor is created.
//
//--------------------------------------------------------------------------//
void CRUDupElimTask::SetupDS()
{
CRUTbl &tbl = GetTable();
CRUEmpCheckVector &ecVector = tbl.GetEmpCheckVector();
// The sweep scans the delta up to the current epoch (not including).
endEpoch_ = tbl.GetCurrentEpoch() - 1;
// begin-epoch = MIN(MV.EPOCH[T]), for MV on T
beginEpoch_ = ecVector.GetMinEpoch();
// Range resolution must be performed if there are ranges in the delta
if (TRUE == ecVector.IsDeltaNonEmpty(
GetBeginEpoch(),
CRUTbl::RANGE)
)
{
isRangeResolv_ = TRUE;
}
BOOL isSingleDeltaNonEmpty = ecVector.IsDeltaNonEmpty(
GetBeginEpoch(),
CRUTbl::SINGLE_ROW
);
// Single-row resolution must be performed if:
// (1) The table is used by an MJV
// (2) There are single-row records in the delta
// (3) The table is not INSERTLOG.
if (TRUE == IsSingleRowResolutionEnforced()
&&
TRUE == isSingleDeltaNonEmpty
&&
FALSE == tbl.IsInsertLog())
{
isSingleRowResolv_ = TRUE;
}
BOOL isCrossTypeResolutionEnforced = IsCrossTypeResolutionEnforced();
// Cross-type duplicates must NOT be resolved in two cases:
// (1) The table is used by multi-txn MVs only (hence,
// the resolution is not enforced).
// (2) There are no single-row records in the delta.
isSkipCrossTypeResolution_ =
(FALSE == isCrossTypeResolutionEnforced
||
FALSE == isSingleDeltaNonEmpty);
// Compute the DE level
if (TRUE == IsSingleRowResolutionEnforced())
{
deLevel_ = CRUDeltaDef::SINGLE_2_SINGLE;
}
else if (TRUE == isCrossTypeResolutionEnforced)
{
deLevel_ = CRUDeltaDef::RANGE_2_SINGLE;
}
else
{
deLevel_ = CRUDeltaDef::RANGE_2_RANGE;
}
// Build the list of the clustering key columns (for the SQL composer)
tbl.BuildKeyColumnList();
}
//--------------------------------------------------------------------------//
// CRUDupElimTask::IsSingleRowResolutionEnforced()
//
// The full-scale conflict resolution (including resolving
// the duplicated between single-row log records) will be
// enforced in two cases:
// (1) The table is used by an incrementally refreshed MJV
// (because the Internal Refresh of MJV requires no
// single-row duplicates).
// (2) "Debug 55" option appears in the command. This option
// is used for testing only, in the DEBUG mode.
//
//--------------------------------------------------------------------------//
BOOL CRUDupElimTask::IsSingleRowResolutionEnforced() const
{
BOOL isSingleRowResolutionEnforced =
GetTable().IsUsedByIncrementalMJV();
#ifdef _DEBUG
CRUOptions &options = CRUGlobals::GetInstance()->GetOptions();
if (NULL != options.FindDebugOption(CRUGlobals::ENFORCE_FULL_DE, ""))
{
isSingleRowResolutionEnforced = TRUE;
}
#endif
return isSingleRowResolutionEnforced;
}
//--------------------------------------------------------------------------//
// CRUDupElimTask::IsCrossTypeResolutionEnforced()
//
// The cross-type conflicts (i.e., range vs single-row) must NOT be
// resolved if all the incrementally refreshed MVs on this table are multi-
// transactional (hence, the INTERNAL REFRESH will filter the cross-type
// duplicates by itself).
//
//--------------------------------------------------------------------------//
BOOL CRUDupElimTask::IsCrossTypeResolutionEnforced() const
{
#ifdef _DEBUG
// The REFRESH_WITH_DE environment variable allows
// the user to enforce the cross-type duplicate elimination always
const char *env = getenv("REFRESH_WITH_DE");
if (NULL != env)
{
return TRUE;
}
#endif
if (TRUE == GetTable().IsUsedOnlyByMultiTxnMvs())
{
return FALSE;
}
return TRUE;
}