//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1992. // // File: IDXTAB.HXX // // Contents: Index Manager // // Classes: CIndexTable // // History: 22-Mar-91 BartoszM Created. // //---------------------------------------------------------------------------- #pragma once #include #include #include #include class CiStorage; class CIndex; class CPersIndex; class CTransaction; //+--------------------------------------------------------------------------- // // Class: CIndexFile // // Purpose: A file of index records // // History: 01-jul-93 BartoszM Created. // 03-mar-94 DwightKr Changed to user persistent streams // //---------------------------------------------------------------------------- class CIndexFile { public: virtual ~CIndexFile(){} virtual void Rewind() = 0; virtual void BackUp() = 0; virtual BOOL ReadRecord(CIndexRecord* pRecord) = 0; }; //+--------------------------------------------------------------------------- // // Class: CIndexTableUsrHdr // // Purpose: User specific header in the index table. This will track the // master merge sequence number. // // History: 3-19-97 srikants Created // //---------------------------------------------------------------------------- class CIndexTableUsrHdr { public: CIndexTableUsrHdr(); unsigned GetMMergeSeqNum() const { return _iMMergeSeqNum; } void IncrMMergeSeqNum() { _iMMergeSeqNum++; } BOOL IsFullSave() const { return _fFullSave; } void SetFullSave() { _fFullSave = TRUE; } void ClearFullSave() { _fFullSave = FALSE; } private: unsigned _iReserved; // // Master Merge sequence number. This has the number of times // a master merge has been performed in this catalog. // unsigned _iMMergeSeqNum; // // This field is used when the index table is transpored. At the // destination, it will be used to ensure that for an incremental // load, the master merge sequence numbers are same. // BOOL _fFullSave; }; //+--------------------------------------------------------------------------- // // Class: CWriteIndexFile // // Purpose: A file of index records // // History: 01-jul-93 BartoszM Created. // 03-mar-94 DwightKr Changed to user persistent streams // //---------------------------------------------------------------------------- class CWriteIndexFile : INHERIT_VIRTUAL_UNWIND, public CIndexFile { DECLARE_UNWIND public: CWriteIndexFile ( PRcovStorageObj & rcovObj ); virtual ~CWriteIndexFile() {} void Rewind() { _xact.Seek(0); _xactPtr = 0; } void BackUp(); BOOL ReadRecord ( CIndexRecord* pRecord ); void WriteRecord ( CIndexRecord* pRecord ); void Commit() { _xact.Commit(); } ULONG GetStorageVersion() { return _rcovObj.GetVersion(); } void IncrMMergeSeqNum(); private: PRcovStorageObj & _rcovObj; CRcovStrmWriteTrans _xact; CRcovStrmWriteIter _iter; ULONG _xactPtr; }; //+--------------------------------------------------------------------------- // // Class: CReadIndexFile // // Purpose: A file of index records // // History: 01-jul-93 BartoszM Created. // 03-mar-94 DwightKr Changed to user persistent streams // //---------------------------------------------------------------------------- class CReadIndexFile : INHERIT_VIRTUAL_UNWIND, public CIndexFile { DECLARE_UNWIND public: CReadIndexFile ( PRcovStorageObj & rcovObj ); virtual ~CReadIndexFile() {} void Rewind() { _xact.Seek(0); _xactPtr = 0; } void BackUp(); BOOL ReadRecord ( CIndexRecord* pRecord ); private: PRcovStorageObj & _rcovObj; CRcovStrmReadTrans _xact; CRcovStrmReadIter _iter; ULONG _xactPtr; }; //+--------------------------------------------------------------------------- // // Class: CNextIndexRecord // // Purpose: Reads in records from file. Only contains // non-empty records (determined by INDEXID)-- doesn't contain // anything useful if Found() returns false. // // History: 16-Mar-92 AmyA Created. // //---------------------------------------------------------------------------- class CNextIndexRecord: public CIndexRecord { public: inline CNextIndexRecord( CIndexFile & indFile ); inline BOOL Found() { return _found; } private: BOOL _found; }; //+--------------------------------------------------------------------------- // // Member: CNextIndexRecord::CNextIndexRecord, public // // Synopsis: Reads IndexRecords in from the file indicated by indFile in a loop, // stopping when either a non-empty record or EOF are reached. // // Notes: Whether or not a non-empty record was found can be determined // by a call to Found(). // // History: 16-Mar-92 AmyA Created. // //---------------------------------------------------------------------------- inline CNextIndexRecord::CNextIndexRecord( CIndexFile & indFile ) { INDEXID iidNotValid = CIndexId( iidInvalid, partidInvalid ); do { _found = indFile.ReadRecord( this ); } while ( _found && ( Iid() == iidNotValid || Iid() == iidInvalid ) ); } //+--------------------------------------------------------------------------- // // Class: CAddReplaceIndexRecord // // Purpose: Reads and writes records from file. Only contains // a useful record if Found() returns true. // // History: 16-Mar-92 AmyA Created. // 29-Feb-95 DwightKr Created WriteRecord() method, // and moved code from destructor there, // since the destructor chould THROW(). // Also changed name to reflect what this // class really does. // //---------------------------------------------------------------------------- class CAddReplaceIndexRecord : public CIndexRecord { public: CAddReplaceIndexRecord( CWriteIndexFile & indFile, INDEXID iid ); void SetIid( INDEXID iid ) { _iid = iid; } void SetType( ULONG type ) { _type = type | _indFile.GetStorageVersion(); } void SetWid( WORKID maxWorkId ) { _maxWorkId = maxWorkId; } void SetObjectId ( WORKID objectId ) { _objectId = objectId; } inline BOOL Found() { return _found; } void WriteRecord(); private: BOOL _found; CWriteIndexFile & _indFile; }; //+--------------------------------------------------------------------------- // // Class: CIndexTable // // Purpose: Manages Indexes. // Contains the table of persistent indexes // and partitions. // // History: 22-Mar-91 BartoszM Created. // 07-Mar-92 AmyA -> FAT // //---------------------------------------------------------------------------- class CIndexTable : public PIndexTable { friend class CIndexTabIter; public: CIndexTable ( CiStorage& storage, CTransaction& xact ); ~CIndexTable(); void AddObject( PARTITIONID partid, IndexType it, WORKID wid ); void AddMMergeObjects( PARTITIONID partid, CIndexRecord & recNewMaster, WORKID widMMLog, WORKID widMMKeyList, INDEXID iidDelOld, INDEXID iidDelNew ); void DeleteObject( PARTITIONID partid, IndexType it, WORKID wid ); virtual void SwapIndexes ( CShadowMergeSwapInfo & info ); virtual void SwapIndexes ( CMasterMergeSwapInfo & info ); PIndexTabIter* QueryIterator(); PStorage& GetStorage(); void RemoveIndex ( INDEXID iid ); void AddIndex( INDEXID iid, IndexType it, WORKID maxWid, WORKID objId); void LokEmpty(); virtual void LokMakeBackupCopy( PStorage & storage, BOOL fFullSave, PSaveProgressTracker & tracker ); void GetUserHdrInfo( unsigned & mMergeSeqNum, BOOL & fFullSave ); private: void AddRecord( CWriteIndexFile & indFile, INDEXID iid, ULONG type, WORKID maxWorkId, WORKID objectId ); void DeleteRecord ( CWriteIndexFile & indFile, INDEXID iid ); void DeleteObject ( CWriteIndexFile & indFile, PARTITIONID partid, IndexType it, WORKID wid ); PRcovStorageObj & GetIndexTableObj() { return *_pRcovObj; } CiStorage& _storage; PRcovStorageObj * _pRcovObj; }; // // This has to be an unwindable object it has CReadIndexFile // as an embedded object which is unwindable. // class CIndexTabIter: public PIndexTabIter { public: CIndexTabIter ( CIndexTable& idxTable ); virtual ~CIndexTabIter(); BOOL Begin(); BOOL NextRecord ( CIndexRecord& record ); private: PStorage & GetStorage() { return _idxTable._storage; } CIndexTable& _idxTable; CReadIndexFile _indFile; }; //+--------------------------------------------------------------------------- // // Member: CIndexTable::DeleteRecord, private // // Synopsis: Marks current record as deleted // // History: 12-Mar-92 AmyA Created. // //---------------------------------------------------------------------------- inline void CIndexTable::DeleteRecord ( CWriteIndexFile & indFile, INDEXID iid ) { CAddReplaceIndexRecord rec( indFile, iid ); if ( rec.Found() ) { rec.SetIid( CIndexId(iidInvalid, partidInvalid) ); rec.WriteRecord(); } }