sl@0: // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: #include "US_STD.H" sl@0: #include "U32STD_DBMS.H" sl@0: sl@0: // Class CDbStoreIndex::CRecover sl@0: sl@0: NONSHARABLE_CLASS(CDbStoreIndex::CRecover) : public CDbTableDatabase::CStepper sl@0: { sl@0: private: sl@0: enum {EClearStep=1}; sl@0: public: sl@0: CRecover(CDbStoreDatabase& aDatabase,const CDbStoreDef& aTable,const CDbStoreIndexDef& anIndex); sl@0: ~CRecover(); sl@0: static inline TInt Steps(TInt aCardinality); sl@0: private: sl@0: TInt StepL(TInt aStep); sl@0: private: sl@0: CDbStoreDatabase& iDatabase; sl@0: const CDbStoreDef& iTable; sl@0: const CDbStoreIndexDef& iIndex; sl@0: CDbTableDatabase::CBuildIndex* iBuild; sl@0: }; sl@0: sl@0: inline TInt CDbStoreIndex::CRecover::Steps(TInt aCardinality) sl@0: {return CDbTableDatabase::CBuildIndex::Steps(aCardinality)+EClearStep;} sl@0: sl@0: CDbStoreIndex::CRecover::CRecover(CDbStoreDatabase& aDatabase,const CDbStoreDef& aTable,const CDbStoreIndexDef& anIndex) sl@0: : iDatabase(aDatabase),iTable(aTable),iIndex(anIndex) sl@0: {} sl@0: sl@0: CDbStoreIndex::CRecover::~CRecover() sl@0: { sl@0: delete iBuild; sl@0: } sl@0: sl@0: TInt CDbStoreIndex::CRecover::StepL(TInt aStep) sl@0: { sl@0: if (iBuild==NULL) sl@0: { // first step sl@0: iBuild=CDbTableDatabase::CBuildIndex::NewL(iDatabase,iTable,iIndex); sl@0: ((CDbStoreIndex&)iBuild->Index()).DiscardL(); sl@0: return aStep-EClearStep; sl@0: } sl@0: aStep=iBuild->StepL(aStep); sl@0: if (aStep==0) sl@0: { // final step sl@0: iDatabase.IndexRecoveredL(); sl@0: delete iBuild; sl@0: iBuild=NULL; sl@0: } sl@0: return aStep; sl@0: } sl@0: sl@0: // Class CDbStoreIndex::CRepair sl@0: sl@0: NONSHARABLE_CLASS(CDbStoreIndex::CRepair) : public CDbTableDatabase::CStepper sl@0: { sl@0: private: sl@0: enum {ERepairStep=1}; sl@0: public: sl@0: CRepair(CDbStoreDatabase& aDatabase,const CDbStoreDef& aTable,const CDbStoreIndexDef& anIndex); sl@0: static inline TInt Steps(); sl@0: private: sl@0: TInt StepL(TInt aStep); sl@0: private: sl@0: CDbStoreDatabase& iDatabase; sl@0: const CDbStoreDef& iTable; sl@0: const CDbStoreIndexDef& iIndex; sl@0: }; sl@0: sl@0: inline TInt CDbStoreIndex::CRepair::Steps() sl@0: {return ERepairStep;} sl@0: sl@0: CDbStoreIndex::CRepair::CRepair(CDbStoreDatabase& aDatabase,const CDbStoreDef& aTable,const CDbStoreIndexDef& anIndex) sl@0: : iDatabase(aDatabase),iTable(aTable),iIndex(anIndex) sl@0: {} sl@0: sl@0: TInt CDbStoreIndex::CRepair::StepL(TInt) sl@0: { sl@0: CDbStoreIndex* index=CDbStoreIndex::NewL(iDatabase,iIndex,iTable); sl@0: CleanupStack::PushL(index); sl@0: index->OpenL(); sl@0: index->RepairL(); sl@0: CleanupStack::PopAndDestroy(); sl@0: return 0; sl@0: } sl@0: sl@0: // Class CDbStoreDatabase sl@0: sl@0: CDbTableDatabase::CStepper* CDbStoreDatabase::RecoverL(TInt& aStep) sl@0: { sl@0: TSglQueIterC iter(SchemaL()); // ensure we have the schema sl@0: TInt count=0; sl@0: const CDbStoreDef* tDef; sl@0: while ((tDef=iter++)!=NULL) sl@0: count+=tDef->Indexes().Count(); sl@0: CMultiStepper* mStepper=CMultiStepper::NewL(count); sl@0: CleanupStack::PushL(mStepper); sl@0: // damaged ones first (as they are invoked last sl@0: count=0; sl@0: iter.SetToFirst(); sl@0: while ((tDef=iter++)!=NULL) sl@0: { sl@0: TInt records=CDbStoreRecords::CardinalityL(Store(),*tDef); sl@0: TSglQueIterC xIter(tDef->Indexes().AsQue()); sl@0: for (const CDbStoreIndexDef* xDef;(xDef=xIter++)!=NULL;) sl@0: { sl@0: if (!CDbStoreIndex::IsDamagedL(*this,*xDef)) sl@0: continue; sl@0: // rebuild from scratch sl@0: CDbStoreIndex::CRecover* rebuild=new(ELeave) CDbStoreIndex::CRecover(*this,*tDef,*xDef); sl@0: mStepper->AddStepper(rebuild,rebuild->Steps(records)); sl@0: ++count; sl@0: } sl@0: } sl@0: if (count==0) sl@0: { // no indexes are actually damaged sl@0: aStep=0; sl@0: CleanupStack::PopAndDestroy(); sl@0: return NULL; sl@0: } sl@0: // repair the other ones after a reclaim sl@0: iter.SetToFirst(); sl@0: while ((tDef=iter++)!=NULL) sl@0: { sl@0: TSglQueIterC xIter(tDef->Indexes().AsQue()); sl@0: for (const CDbStoreIndexDef* xDef;(xDef=xIter++)!=NULL;) sl@0: { sl@0: if (CDbStoreIndex::IsDamagedL(*this,*xDef)) sl@0: continue; sl@0: // repair from sequence set sl@0: CDbStoreIndex::CRepair* repair=new(ELeave) CDbStoreIndex::CRepair(*this,*tDef,*xDef); sl@0: mStepper->AddStepper(repair,repair->Steps()); sl@0: } sl@0: } sl@0: iPagePool->Discard(); sl@0: iPagePool->ReclaimAllL(); // recover all page pool space sl@0: aStep=mStepper->TotalSteps(); sl@0: CleanupStack::Pop(); sl@0: return mStepper; sl@0: }