blob: 702be6158433a94e803960e6ca2f8aed479a8188 [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: RuEmpCheckVector.cpp
* Description: Implementation of class CRUEmpCheckVector
*
*
* Created: 08/28/2000
* Language: C++
*
*
*
******************************************************************************
*/
#include "RuEmpCheckVector.h"
#include "uofsIpcMessageTranslator.h"
//--------------------------------------------------------------------------//
// Constructors and destructor
//--------------------------------------------------------------------------//
CRUEmpCheckVector::CRUEmpCheckVector() :
pVec_(NULL),
size_(0),
isFinal_(FALSE)
{}
CRUEmpCheckVector::CRUEmpCheckVector(const CRUEmpCheckVector &other) :
size_(other.size_),
isFinal_(other.isFinal_)
{
if (0 == size_)
{
return;
}
pVec_ = new Elem[size_];
for (Int32 i=0; i<size_; i++)
{
pVec_[i] = other.pVec_[i]; // Default copy
}
}
CRUEmpCheckVector::~CRUEmpCheckVector()
{
delete[] pVec_;
}
//--------------------------------------------------------------------------//
// CRUEmpCheckVector::LoadData()
//--------------------------------------------------------------------------//
void CRUEmpCheckVector::LoadData(CUOFsIpcMessageTranslator &translator)
{
// Handle size_ data member
translator.ReadBlock(&size_, sizeof(Lng32));
// Handle final_ data member
translator.ReadBlock(&isFinal_,sizeof(BOOL));
if (NULL == pVec_)
{
pVec_ = new Elem[size_];
}
// Handle pVec_ data member
for (Int32 i=0; i<size_; i++)
{
translator.ReadBlock(&(pVec_[i].epoch_),sizeof(TInt32));
translator.ReadBlock(&(pVec_[i].checkBitmap_), sizeof(Lng32));
}
}
//--------------------------------------------------------------------------//
// CRUEmpCheckVector::StoreData()
//--------------------------------------------------------------------------//
void CRUEmpCheckVector::StoreData(CUOFsIpcMessageTranslator &translator)
{
// Handle size_ data member
translator.WriteBlock(&size_, sizeof(Lng32));
// Handle final_ data member
translator.WriteBlock(&isFinal_,sizeof(BOOL));
// Handle pVec_ data member
for (Int32 i=0; i<size_; i++)
{
translator.WriteBlock(&(pVec_[i].epoch_),sizeof(TInt32));
translator.WriteBlock(&(pVec_[i].checkBitmap_), sizeof(Lng32));
}
}
//--------------------------------------------------------------------------//
// CRUEmpCheckVector::operator =
//--------------------------------------------------------------------------//
CRUEmpCheckVector &CRUEmpCheckVector::
operator = (const CRUEmpCheckVector& other)
{
if (this == &other)
{
return *this;
}
if (NULL != pVec_)
{
RUASSERT(size_ == other.size_);
}
else
{
size_ = other.size_;
pVec_ = new Elem[size_];
}
for (Int32 i=0; i<size_; i++)
{
pVec_[i] = other.pVec_[i]; // Default copy
}
return *this;
}
//--------------------------------------------------------------------------//
// CRUEmpCheckVector::IsDeltaNonEmpty()
//
// Does the delta contain the certain type of record starting from
// this epoch?
//
// Let's refer to the corresponding bit in the bitmap as to a flag.
// The flags in the vector should always be non-ascending, i.e.,
// this picture can happen:
//
// EPOCH 200 202 205
// FLAG TRUE TRUE FALSE
//
// but this one cannot:
//
// EPOCH 200 202 205
// FLAG FALSE FALSE TRUE
//
// Hence, the delta is not empty if there is an element *el*
// in the vector for which:
// (1) el.epoch >= epoch && (2) el.flag == TRUE
//
// For the epoch value which is different from MV.EPOCH[T] for any
// MV on T, the returned value is equal to the one for the closest
// smaller epoch in the vector.
//
//--------------------------------------------------------------------------//
BOOL CRUEmpCheckVector::IsDeltaNonEmpty(TInt32 epoch, Lng32 checkMask) const
{
RUASSERT(NULL != pVec_);
for (Int32 i=size_-1; i>=0; i--)
{
Elem &el = pVec_[i];
if (0 != (checkMask & el.checkBitmap_))
{
return TRUE; // Found it!
}
if (el.epoch_ <= epoch)
{
break; // No point for more checks.
}
}
return FALSE;
}
//--------------------------------------------------------------------------//
// Return FALSE if there are any single row deletes or updates in the delta.
//--------------------------------------------------------------------------//
BOOL CRUEmpCheckVector::IsDeltaInsertOnly(TInt32 epoch) const
{
RUASSERT(NULL != pVec_);
// Look for deleted or updates
for (Int32 i=size_-1; i>=0; i--)
{
Elem &el = pVec_[i];
if (0 != (CRUTbl::SINGLE_ROW_OTHER & el.checkBitmap_))
{
return FALSE; // Found it!
}
if (el.epoch_ <= epoch)
{
break; // No point for more checks.
}
}
return TRUE;
}
//--------------------------------------------------------------------------//
// CRUEmpCheckVector::Build()
//
// Build the vector (with all the flags initialized to FALSE)
// based on the client incremental Refresh tasks. Given the map of
// begin-epochs, sort the vector by the value of begin-epoch.
//
//--------------------------------------------------------------------------//
void CRUEmpCheckVector::Build()
{
size_ = epMap_.GetCount();
if (0 == size_)
{
return;
}
pVec_ = new Elem[size_];
CDSMapPosition<Lng32> mpos;
Lng32 i, ep, val;
for (i=0, epMap_.GetStartPosition(mpos); TRUE == mpos.IsValid(); i++)
{
epMap_.GetNextAssoc(mpos, ep, val);
pVec_[i].epoch_ = ep;
}
RUASSERT(i == size_);
qsort(pVec_, size_, sizeof(Elem), CompareElem);
}
//--------------------------------------------------------------------------//
// CRUEmpCheckVector::SetDeltaNonEmpty()
//
// Mark that the log contains records of certain type starting
// from this epoch (and hence, from all the epochs smaller than it).
//
//--------------------------------------------------------------------------//
void CRUEmpCheckVector::
SetDeltaNonEmpty(TInt32 epoch, CRUTbl::IUDLogContentType ct)
{
for (Int32 i=0; i<size_; i++)
{
Elem &el = pVec_[i];
el.checkBitmap_ |= ct; // Raise the bit
if (epoch == el.epoch_)
{
return;
}
}
// The target epoch was never encountered - error!
RUASSERT(FALSE);
}
//--------------------------------------------------------------------------//
// CRUEmpCheckVector::SetAllDeltasNonEmpty()
//
// Called by: CRUSimpleRefreshTaskExecutor::FinalMetadataUpdate()
//
// After an ON REQUEST MV is refreshed *incrementally*, we suppose
// that it has written something to the log. Hence, its delta
// is non-empty for each using ON REQUEST MV.
//
//--------------------------------------------------------------------------//
void CRUEmpCheckVector::SetAllDeltasNonEmpty()
{
for (Int32 i=0; i<size_; i++)
{
pVec_[i].checkBitmap_ |= CRUTbl::SINGLE_ROW;
}
}
//--------------------------------------------------------------------------//
// CRUEmpCheckVector::CompareElem()
//
// The function serves for the quicksort criteria.
//--------------------------------------------------------------------------//
Int32 CRUEmpCheckVector::CompareElem(const void *pEl1, const void *pEl2)
{
return (((CRUEmpCheckVector::Elem *)pEl1)->epoch_
<
((CRUEmpCheckVector::Elem *)pEl2)->epoch_
) ? -1 : 1;
}