void CRUAuditRefreshTaskExecutor::ResetObjectsAvailable() { CRUMVList &mvList = GetRefreshTask()->GetMVList(); DSListPosition pos = mvList.GetHeadPosition(); while (NULL != pos) { CRUMV *pMV = mvList.GetNext(pos); BOOL mvUpdated = FALSE; // if hasn't been set to initialized, initialize it if( CDDObject::eINITIALIZED != pMV->GetMVStatus() ) { pMV->SetMVStatus(CDDObject::eINITIALIZED); mvUpdated = TRUE; } if (mvUpdated) { pMV->SaveMetadata(); } } if (TRUE == isPopindex_ && 0 < numOfIndexes_) { // Turn all indexes to available state ExecuteIndexStatmenents(*pAuditAvailableIndeXdynamicContainer_, IDS_RU_INDEXSTATUS_FAILED); } }
void CRUTbl::BuildEmpCheckVector() { // Verify that the vector is non-initialized RUASSERT(FALSE == pEmpCheckVector_->IsValid()); // CRUEmpCheckTask is created only if there is // at least one incrementally refreshed MV. RUASSERT(FALSE == pIncInvolvedMVsUsingMe_->IsEmpty()); TInt64 tblUid = GetUID(); DSListPosition lpos = pIncInvolvedMVsUsingMe_->GetHeadPosition(); while (NULL != lpos) { CRUMV *pMV = pIncInvolvedMVsUsingMe_->GetNext(lpos); RUASSERT (TRUE == pMV->IsInvolved() && FALSE == pMV->WillBeRecomputed()); // Register the epoch in the vector ... pEmpCheckVector_->AddEpochForCheck(pMV->GetEpoch(tblUid)); } pEmpCheckVector_->Build(); }
//--------------------------------------------------------------------------// // CRUCache::FetchForceData() // //--------------------------------------------------------------------------// void CRUCache::FetchForceData() { CRUForceOptionsParser forceParser; forceParser.SetFile( CRUGlobals::GetInstance()->GetOptions().GetForceFilename()); forceParser.Parse(); CRUForceOptions& forceOption = forceParser.GetForceOptions(); // Place the force data on the involved mv's. CRUMVList &mvList = GetMVList(); DSListPosition pos = mvList.GetHeadPosition(); while (NULL != pos) { CRUMV *pMV = mvList.GetNext(pos); if (FALSE == pMV->IsInvolved()) { continue; } UpdateForceOptionForMV(forceOption, pMV); } }
void CRURefreshSQLComposer::AddPipeLineClause() { CRUMVList &mvList = GetRefreshTask().GetMVList(); RUASSERT(mvList.GetCount() > 1); DSListPosition pos = mvList.GetHeadPosition(); mvList.GetNext(pos); // Skip the root MV // Generate root clause CRUMV *pTopMV = mvList.GetNext(pos); sql_ += " PIPELINE " ; sql_ += "(" + pTopMV->GetFullName() + ")"; // Continue with the upper mv's while (NULL != pos) { sql_ += pTopMV->GetFullName(); // Retrieve the next MV from the list pTopMV = mvList.GetNext(pos); sql_ += " PIPELINE " ; sql_ += "(" + pTopMV->GetFullName() + ")"; if (NULL != pos) { sql_ += ","; } else { return; } } }
void CRUCache::FixupMVTblInterfaces() { DSListPosition pos = mvList_.GetHeadPosition(); while (NULL != pos) { CRUMV *pMV = mvList_.GetNext(pos); if (FALSE == pMV->IsInvolved()) { continue; // Skip the non-involved MVs } CRUTbl *pTbl = GetTable(pMV->GetUID()); if (NULL == pTbl) { continue; // No table object in the cache, skip } // Setup pointers MV <---> table pMV->SetTblInterface(pTbl); pTbl->SetMVInterface(pMV); } }
void CRUTbl::BuildListOfIncrementalInvolvedMVsUsingMe() { // Verify that the list is not initialized already RUASSERT(TRUE == pIncInvolvedMVsUsingMe_->IsEmpty()); DSListPosition pos = pOnRequestInvolvedMVsUsingMe_->GetHeadPosition(); while (NULL != pos) { CRUMV *pMV = pOnRequestInvolvedMVsUsingMe_->GetNext(pos); RUASSERT(CDDObject::eON_REQUEST == pMV->GetRefreshType() && TRUE == pMV->IsInvolved() ); if (TRUE == pMV->WillBeRecomputed()) { continue; } pIncInvolvedMVsUsingMe_->AddTail(pMV); CDDObject::EMVQueryType qt = pMV->GetQueryType(); if (CDDObject::eMJV == qt || CDDObject::eOTHER == qt // Is this MJV on single table? ) { isUsedByIncrementalMJV_ = TRUE; } } }
//------------------------------------------------------------------------// // CRUTbl::Dump() //------------------------------------------------------------------------// // LCOV_EXCL_START :dpb void CRUTbl::Dump(CDSString &to, BOOL isExtended) { char statusStr[10]; to += "\nUSED OBJECT " + GetFullName() + " ("; if (TRUE == IsRegularTable()) { to += "regular table)\n"; } else { to += "materialized view)\n"; } sprintf(statusStr, "%d", GetStatus()); to += "Status = "; to += statusStr; if (0 != GetStatus()) to += "(error)"; to += "\nMVs using me:\n"; DSListPosition pos = GetMVsUsingMe().GetHeadPosition(); while (NULL != pos) { CRUMV *pMV = GetMVsUsingMe().GetNext(pos); to += "\t" + (pMV->GetFullName()) + "\n"; } }
CRUCache::~CRUCache() { // Normally, all of the DDOL MV/table objects are in // the eClosed state at this point. However, // if the destructor is called from inside an exception // handler when some DDOL object is left in the eModified // state, the utility should not attempt to save the object // to the catalog. DSListPosition pos = mvList_.GetHeadPosition(); while (NULL != pos) { CRUMV *pMV = mvList_.GetNext(pos); pMV->CancelChanges(); } pos = tableList_.GetHeadPosition(); while (NULL != pos) { CRUTbl *pTbl = tableList_.GetNext(pos); pTbl->CancelChanges(); } // Since sqlNode_ is an object (not a pointer), // its destructor is called automatically, // therefore disposing the cloud of DD objects. // Since mvList_ and tableList_ *own* the referenced objects, // there is no need to apply the RemoveAll() method to them. }
BOOL CRUTbl::IsUsedOnlyByMultiTxnMvs() const { if (TRUE == pIncInvolvedMVsUsingMe_->IsEmpty()) { return FALSE; } DSListPosition pos = pIncInvolvedMVsUsingMe_->GetHeadPosition(); while (NULL != pos) { CRUMV *pMV = pIncInvolvedMVsUsingMe_->GetNext(pos); RUASSERT( CDDObject::eON_REQUEST == pMV->GetRefreshType() && TRUE == pMV->IsInvolved() ); if (0 == pMV->GetCommitNRows()) { return FALSE; } } return TRUE; }
void CRUTbl::CheckIfLongLockNeeded() { if (TRUE == IsLongLockNeeded()) { // Someone else (the equivalence set analyzer) // has already set the flag. return; } CDDObject::ERangeLogType rlType = GetRangeLogType(); if (CDDObject::eAUTOMATIC == rlType // Case #1 || CDDObject::eMIXED == rlType) { SetLongLockIsNeeded(); return; } DSListPosition pos = pOnRequestInvolvedMVsUsingMe_->GetHeadPosition(); while (NULL != pos) { CRUMV *pMV = pOnRequestInvolvedMVsUsingMe_->GetNext(pos); if (FALSE == pMV->IsSelfMaintainable() // Case #2 || TRUE == pMV->WillBeRecomputed() // Case #3 ) { SetLongLockIsNeeded(); return; } } }
void CRUCache::SetupRecomputeProperty() { DSListPosition pos = mvList_.GetHeadPosition(); while (NULL != pos) { CRUMV *pMV = mvList_.GetNext(pos); pMV->SetupRecomputeProperty(isTotalRecompute_); } }
void CRUTbl::PropagateDEStatisticsToUsingMVs() { DSListPosition pos = pIncInvolvedMVsUsingMe_->GetHeadPosition(); while (NULL != pos) { CRUMV *pMV = pIncInvolvedMVsUsingMe_->GetNext(pos); pMV->PropagateDEStatistics(*this); } }
void CRUTbl::PropagateEmpCheckToUsingMVs() { RUASSERT(TRUE == GetEmpCheckVector().IsFinal()); DSListPosition pos = pIncInvolvedMVsUsingMe_->GetHeadPosition(); while (NULL != pos) { CRUMV *pMV = pIncInvolvedMVsUsingMe_->GetNext(pos); pMV->PropagateEmpCheck(*this); } }
void CRUTbl::PropagateRecomputeToUsingMVs() { RUASSERT(TRUE == IsInvolvedMV() && TRUE == GetMVInterface()->WillBeRecomputed()); DSListPosition pos = pIncInvolvedMVsUsingMe_->GetHeadPosition(); while (NULL != pos) { CRUMV *pMV = pIncInvolvedMVsUsingMe_->GetNext(pos); pMV->SetRefreshPatternMask(CRUMV::RECOMPUTE); } }
CRUMV *CRUCache::FetchSingleNonInvolvedMV(CDDMV *pddMV) { // Create a new wrapper object for a non-involved MV, // leave its reference list empty CRUMV *pMV = new CRUMV(pddMV); mvList_.AddTail(pMV); // Fetch the epoch data pMV->FetchMetadata(); return pMV; }
CRUMV *CRUCache::GetMV(TInt64 objUid) const { DSListPosition pos = mvList_.GetHeadPosition(); while (NULL != pos) { CRUMV *pMV = mvList_.GetNext(pos); if (pMV->GetUID() == objUid) { return pMV; } } return NULL; }
void CRUTblEquivSetBuilder::AddRecomputedMVs() { DSListPosition mvPos = recomputeMVsList_.GetHeadPosition(); while (NULL != mvPos) { CRUMV *pMV = recomputeMVsList_.GetNext(mvPos); if (0 == pMV->GetNumDirectlyUsedMVs() || 1 == pMV->GetTablesUsedByMe().GetCount()) { continue; } AddRecomputeTree(pMV); } }
void CRUCache::FetchNonInvolvedUsedObjectsMetadata() { DSListPosition pos = mvList_.GetHeadPosition(); while (NULL != pos) { CRUMV *pMV = mvList_.GetNext(pos); if (FALSE == pMV->IsInvolved() || CDDObject::eON_REQUEST != pMV->GetRefreshType()) { continue; } if (NULL == GetTable(pMV->GetUID())) { CDDSchema *pddSch = GetDDSchemaByName(pMV->GetCatName(), pMV->GetSchName()); CDDMV *pddMV = GetDDMVByName(pddSch, pMV->GetName()); CRUTbl *pTbl = new CRUMVTbl(pddMV); pTbl->FetchMetadata(); tableList_.AddTail(pTbl); } } }
void CRUCache::Dump(CDSString &to, BOOL isExtended) const { to += "\n\t\tCACHE DUMP\n"; DSListPosition pos = mvList_.GetHeadPosition(); while (NULL != pos) { CRUMV *pMV = mvList_.GetNext(pos); pMV->Dump(to, isExtended); } pos = tableList_.GetHeadPosition(); while (NULL != pos) { CRUTbl *pTbl = tableList_.GetNext(pos); pTbl->Dump(to, isExtended); } }
BOOL CRUCache::IsOnRequestMVInvolved() { DSListPosition pos = mvList_.GetHeadPosition(); while (NULL != pos) { CRUMV *pMV = mvList_.GetNext(pos); if (TRUE == pMV->IsInvolved() && CDDMV::eON_REQUEST == pMV->GetRefreshType() ) { return TRUE; } } return FALSE; }
void CRUCache::FetchNonInvolvedMVsMetadata() { DSListPosition tpos = tableList_.GetHeadPosition(); while (NULL != tpos) { CRUTbl *pTbl = tableList_.GetNext(tpos); // Retrieve the table's private dependency list CDDUIDTripleList &privTblList = pTbl->GetUIDsOfAllMVsUsingMe(); DSListPosition mvpos = privTblList.GetHeadPosition(); while (NULL != mvpos) { CDDUIDTriple &uidt = privTblList.GetNext(mvpos); CRUMV *pMV = GetMV(uidt.objUID); if (NULL == pMV) { // The MV is non-involved, fetch the DD object CDDMV *pddMV = GetDDMVByUID(uidt); // If the MV is not ON REQUEST, skip it if (CDDObject::eON_REQUEST != pddMV->GetRefreshType()) { continue; } pMV = FetchSingleNonInvolvedMV(pddMV); } if (FALSE == pMV->IsInvolved()) { // If the MV is involved, the pointer exists already pTbl->AddRefToUsingMV(pMV); } } } }
void CRUUnAuditRefreshTaskExecutor::SetObjectsUnavailable() { if (TRUE == isPopindex_ && 0 < numOfIndexes_) { // Turn all indexes to unavailable state ExecuteIndexStatmenents(*pUnAuditUnavailableIndeXdynamicContainer_, IDS_RU_INDEXSTATUS_FAILED); } CRUMVList &mvList = GetRefreshTask()->GetMVList(); DSListPosition pos = mvList.GetHeadPosition(); while (NULL != pos) { CRUMV *pMV = mvList.GetNext(pos); if (CDDObject::eNO_AUDIT_ON_REFRESH == pMV->GetAuditType() // || // CDDObject::eAUDIT == pMV->GetAuditType() // DO NOT TURN THE AUDITED MV'S TABLE TO NON-AUDITED // UNTIL THE BUG WITH TURNING THE AUDIT ATTRIBUTE IS FIXED !!! // Right now, we assume that the MV's table is initially // non-audited if this task executor is picked up. ) { // Alter table audit uses "ALTER TABLE" syntax // and it cannot be performed if there is a DDL lock. // Due to the transaction protection , for any other transaction // the ddl locks will preserve continuity. pMV->ReleaseDDLLock(); pMV->SetMVTableAudit(FALSE); pMV->SaveMetadata(); pMV->CreateDDLLock(); } pMV->SetMVStatus(CDDObject::eUNAVAILABLE); pMV->SaveMetadata(); } // Since the mv ddl lock was released and recreated, the popindex // sql statements need to be recomposed if( TRUE == isPopindex_ && 0 < numOfIndexes_ ) { ComposeIndexesSql(); } }
void CRUUnAuditRefreshTaskExecutor::ResetObjectsAvailable() { CRUMVList &mvList = GetRefreshTask()->GetMVList(); DSListPosition pos = mvList.GetHeadPosition(); while (NULL != pos) { CRUMV *pMV = mvList.GetNext(pos); if (CDDObject::eNO_AUDIT != pMV->GetAuditType()) { // Alter table audit uses "ALTER TABLE" syntax // and it cannot be performed if there is a DDL lock. // Due to the transaction protection , for any other transaction // the ddl locks will preserve continuity. pMV->ReleaseDDLLock(); pMV->SetMVTableAudit(TRUE); pMV->SaveMetadata(); pMV->CreateDDLLock(); } RUASSERT(CDDObject::eUNAVAILABLE == pMV->GetMVStatus()); pMV->SetMVStatus(CDDObject::eINITIALIZED); pMV->SaveMetadata(); } if (TRUE == isPopindex_ && 0 < numOfIndexes_) { // must recompose since DDL locks were released/created ComposeIndexesSql(); // Turn all indexes to available state ExecuteIndexStatmenents(*pUnAuditAvailableIndeXdynamicContainer_, IDS_RU_INDEXSTATUS_FAILED); } }
void CRUAuditRefreshTaskExecutor::SetObjectsUnavailable() { if (TRUE == isPopindex_ && 0 < numOfIndexes_) { // Turn all indexes to unavailable state ExecuteIndexStatmenents(*pAuditUnavailableIndeXdynamicContainer_, IDS_RU_INDEXSTATUS_FAILED); } // first turn the audit flag ON for the MV table // and set the MV to unavailable CRUMVList &mvList = GetRefreshTask()->GetMVList(); DSListPosition pos = mvList.GetHeadPosition(); while (NULL != pos) { CRUMV *pMV = mvList.GetNext(pos); // Alter table audit uses "ALTER TABLE" syntax // and it cannot be performed if there is a DDL lock. // Due to the transaction protection , for any other transaction // the ddl locks will preserve continuity. pMV->ReleaseDDLLock(); pMV->SetMVTableAudit(TRUE); pMV->SaveMetadata(); pMV->CreateDDLLock(); // if hasn't been set to initialized, initialize it if( CDDObject::eINITIALIZED != pMV->GetMVStatus() ) { pMV->SetMVStatus(CDDObject::eUNAVAILABLE); pMV->SaveMetadata(); } } // Since the mv ddl lock was released and recreated, the popindex // sql statements need to be recomposed if( TRUE == isPopindex_ && 0 < numOfIndexes_ ) { ComposeIndexesSql(); } }
void CRUCache::FetchSingleInvolvedMV(CDDMV *pddMV) { CRUMV *pMV = new CRUMV(pddMV); pMV->SetInvolved(); // Read the REFRESH-specific metadata pMV->FetchMetadata(); // Take care not to cancel the dangling DDL lock accidentally. // For example, if the MV is multi-transactional, and has a // DDL lock following the previous Refresh failure - it is // forbidden to remove the DDL lock as long as the MV is not // refreshed successfully. pMV->SetReleaseDDLLock(pddMV->CanCancelDDLLock()); // Ignore User Maintainable MVs. if (CDDObject::eBY_USER == pMV->GetRefreshType()) { delete pMV; return; } mvList_.AddTail(pMV); // Register the MV for the further DDL lock handling ddlLockHandler_.AddObject(pMV); if (TRUE == isCancelOnly_) { return; } // Retrieve whether the user has Insert/Select/Delete privilege for this MV pMV->FetchPrivileges(); }
void CRUTblEquivSetBuilder::AddRecomputeTree(CRUMV *pMV) { RUASSERT(CDDObject::eRECOMPUTE == pMV->GetRefreshType()); if (TRUE == GetDisJointAlg().HasVertex(pMV->GetUID())) { // The mv is already in the graph and his sub tree must also be there // by induction return; } GetDisJointAlg().AddVertex(pMV->GetUID()); // Go over all the childs CRUTblList &tblList = pMV->GetTablesUsedByMe(); DSListPosition tblPos = tblList.GetHeadPosition(); while (NULL != tblPos) { CRUTbl *pTbl = tblList.GetNext(tblPos); if (TRUE == pTbl->IsFullySynchronized()) { GetDisJointAlg().AddEdge(pTbl->GetUID(),pMV->GetUID()); AddSyncTable(pTbl); pTbl->SetLongLockIsNeeded(); continue; } if (FALSE == pTbl->IsInvolvedMV()) { // This is not an involved mv do not add it to the set. // A not involved mv does not require syncronization // because it may only be changed by the refresh utility // and this is prevented by the ddl locks that are place on this // object continue; } // The object is an mv - if its on request we should do nothing // forcing lock may be skipped and all involved on request // are already in the graph GetDisJointAlg().AddEdge(pTbl->GetUID(),pMV->GetUID()); CRUMV *pNextMV = pTbl->GetMVInterface(); RUASSERT(NULL != pNextMV); if (CDDObject::eON_REQUEST == pNextMV->GetRefreshType() ) { // All on requests mv's are already in the graph continue; } RUASSERT(CDDObject::eRECOMPUTE == pNextMV->GetRefreshType()); // call this function recursively for adding all sub tree AddRecomputeTree(pNextMV); } }