blob: 2a8e9fb3dac0e139074231acf6019be85a09b59b [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: RuCacheDDLLockHandler.cpp
* Description: Implementation of class CRUCacheDDLLockHandler.
*
*
* Created: 02/10/2000
* Language: C++
*
*
*
******************************************************************************
*/
#include "RuCacheDDLLockHandler.h"
#include "RuGlobals.h"
#include "RuOptions.h"
#include "RuJournal.h"
//--------------------------------------------------------------------------//
// Constructor
//--------------------------------------------------------------------------//
CRUCacheDDLLockHandler::CRUCacheDDLLockHandler() :
doHandle_(TRUE),
didDDLLockErrorsHappen_(FALSE),
pObjSortedArray_(NULL),
objMap_(HASH_SIZE)
{
CRUGlobals *pGlobals = CRUGlobals::GetInstance();
CRUOptions &options = pGlobals->GetOptions();
if (CRUOptions::DO_ONLY_LC == options.GetLogCleanupType())
{
// When the utility is applied with DO ONLY LOG CLEANUP option,
// DDL locks are not required.
doHandle_ = FALSE;
}
#ifdef _DEBUG
CRUOptions::DebugOption *pDO =
options.FindDebugOption(CRUGlobals::DUMP_DS, "");
if (NULL != pDO)
{
doHandle_ = FALSE; // The invocation is for the DS dump only
}
#endif
}
//--------------------------------------------------------------------------//
// Destructor
//--------------------------------------------------------------------------//
CRUCacheDDLLockHandler::~CRUCacheDDLLockHandler()
{
// Free the sorted array of pointers
if (NULL != pObjSortedArray_)
{
delete [] pObjSortedArray_;
}
// Free the data owned by the hash table
CDSMapPosition<ObjectLink *> pos;
ObjectLink *pLink;
TInt64 *uid;
objMap_.GetStartPosition(pos);
while (TRUE == pos.IsValid())
{
objMap_.GetNextAssoc(pos, uid, pLink);
delete pLink;
}
objMap_.RemoveAll();
}
//--------------------------------------------------------------------------//
// CRUCacheDDLLockHandler::AddObject()
//
// Store the pointer to the object in a temporary object (link),
// which will be pointed from the hash table.
//
// This is an ugly usage of a VERY ugly implementation of TInt64Map.
//
//--------------------------------------------------------------------------//
void CRUCacheDDLLockHandler::AddObject(CRUObject *pObj)
{
if (FALSE == doHandle_)
{
return;
}
RUASSERT (NULL != pObj);
ObjectLink *pLink = new ObjectLink(pObj);
objMap_[&(pLink->uid_)] = pLink;
}
//--------------------------------------------------------------------------//
// CRUCacheDDLLockHandler::HandleDDLLocks()
//
// Handle (acquire/replace/cancel) the DDL lock associated with each
// involved objects, in order to provide mutual exclusion from
// the concurrent DDL and utility operations.
//
// The traversal of involved objects is done in the UID order, for
// theoretical deadlock prevention (although the deadlock scenario
// is VERY unlikely).
//
//--------------------------------------------------------------------------//
void CRUCacheDDLLockHandler::HandleDDLLocks(BOOL isCancelOnly)
{
if (FALSE == doHandle_)
{
return;
}
CRUJournal &journal = CRUGlobals::GetInstance()->GetJournal();
SortObjectsByUid();
for (Int32 i=0; i<objMap_.GetCount(); i++)
{
CRUObject *pObj = pObjSortedArray_[i]->pObj_;
// Perform the CatApi request(s) ...
pObj->HandleDDLLockInCache(isCancelOnly);
if (0 != pObj->GetStatus())
{
// For some reason, the DDL lock could not be dropped.
if (TRUE == isCancelOnly)
{
// If this is the CANCEL mode, report to the outfile.
journal.LogError(pObj->GetErrorDesc());
didDDLLockErrorsHappen_ = TRUE;
}
else
{
// This is the "normal" mode of execution.
// The error message will be copied from the object
// to some Refresh task, and will be printed by the
// flow controller.
}
}
}
}
//--------------------------------------------------------------------------//
// CRUCacheDDLLockHandler::SortObjectsByUid()
//--------------------------------------------------------------------------//
void CRUCacheDDLLockHandler::SortObjectsByUid()
{
RUASSERT(NULL == pObjSortedArray_);
Lng32 size = objMap_.GetCount();
// Copy the pointers to the links to the array first ...
pObjSortedArray_ = new PObjectLink[size];
CDSMapPosition<ObjectLink *> pos;
ObjectLink *pLink;
TInt64 *uid;
objMap_.GetStartPosition(pos);
for (Int32 i=0; TRUE == pos.IsValid(); i++)
{
objMap_.GetNextAssoc(pos, uid, pLink);
pObjSortedArray_[i] = pLink;
}
// ... and sort the array
qsort(pObjSortedArray_, size, sizeof(PObjectLink), CompareElem);
}
//--------------------------------------------------------------------------//
// CRUCacheDDLLockHandler::CompareElem()
//
// The function serves for the quicksort criteria.
//--------------------------------------------------------------------------//
Int32 CRUCacheDDLLockHandler::CompareElem(const void *pEl1, const void *pEl2)
{
CRUCacheDDLLockHandler::ObjectLink *pLink1 =
*((CRUCacheDDLLockHandler::PObjectLink *)pEl1);
CRUCacheDDLLockHandler::ObjectLink *pLink2 =
*((CRUCacheDDLLockHandler::PObjectLink *)pEl2);
return (pLink1->uid_ < pLink2->uid_) ? -1 : 1;
}