//+------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1992. // // File: fat.hxx // // Contents: Header file for fat classes // // Classes: CFatSect - sector sized array of sector info // CFatVector - resizable array of CFatSect // CFat - Grouping of FatSect // // History: 18-Jul-91 PhilipLa Created. // //-------------------------------------------------------------------- #ifndef __FAT_HXX__ #define __FAT_HXX__ #include #define DEB_FAT (DEB_ITRACE|0x00010000) //+---------------------------------------------------------------------- // // Class: CFatSect (fs) // // Purpose: Holds one sector worth of FAT data // // Interface: getsize - Returns the size of the FAT (in sectors) // contents - Returns contents of any given FAT entry // // History: 18-Jul-91 PhilipLa Created. // // Notes: // //----------------------------------------------------------------------- #if _MSC_VER == 700 #pragma warning(disable:4001) #elif _MSC_VER >= 800 #pragma warning(disable:4200) #endif class CFatSect { public: SCODE Init(FSOFFSET uEntries); SCODE InitCopy(USHORT uSize, CFatSect *pfsOld); inline SECT GetSect(const FSOFFSET sect) const; inline void SetSect(const FSOFFSET sect,const SECT sectNew); inline SECT GetNextFat(USHORT uSize) const; inline void SetNextFat(USHORT uSize, const SECT sect); private: SECT _asectEntry[]; }; #if _MSC_VER == 700 #pragma warning(default:4001) #elif _MSC_VER >= 800 #pragma warning(default:4200) #endif inline SECT CFatSect::GetSect(const FSOFFSET sect) const { return _asectEntry[sect]; } inline void CFatSect::SetSect(const FSOFFSET sect, const SECT sectNew) { _asectEntry[sect] = sectNew; } inline SECT CFatSect::GetNextFat(USHORT uSize) const { return _asectEntry[uSize]; } inline void CFatSect::SetNextFat(USHORT uSize, const SECT sect) { _asectEntry[uSize] = sect; } //+------------------------------------------------------------------------- // // Class: CFatVector (fv) // // Purpose: *Finish This* // // Interface: // // History: 02-Sep-92 PhilipLa Created. // // Notes: // //-------------------------------------------------------------------------- class CFatVector: public CPagedVector { public: inline CFatVector( const SID sid); inline void InitCommon(FSOFFSET csectBlock, FSOFFSET csectTable); SCODE InitPage(FSINDEX iPage); inline FSOFFSET GetSectBlock() const; inline FSOFFSET GetSectTable() const; inline SCODE GetTable( const FSINDEX iTable, const DWORD dwFlags, CFatSect **pfs); private: FSOFFSET _csectTable; FSOFFSET _csectBlock; }; inline CFatVector::CFatVector( const SID sid) : CPagedVector(sid) { } inline void CFatVector::InitCommon( FSOFFSET csectBlock, FSOFFSET csectTable) { _csectBlock = csectBlock; _csectTable = csectTable; } //+------------------------------------------------------------------------- // // Method: CFatVector::GetSectTable, public // // Synopsis: Returns count of sector entries per table // // Returns: count of sector entries per table // // History: 08-Jul-92 AlexT Created. // //-------------------------------------------------------------------------- inline FSOFFSET CFatVector::GetSectTable() const { return _csectTable; } //+------------------------------------------------------------------------- // // Method: CFatVector::GetSectBlock, public // // Synopsis: Returns count of sector entries per block // // Returns: count of sector entries per block // // History: 01-Sep-92 PhilipLa Created. // //-------------------------------------------------------------------------- inline FSOFFSET CFatVector::GetSectBlock() const { return _csectBlock; } //+------------------------------------------------------------------------- // // Method: CFatVector::GetTable, public // // Synopsis: Return a pointer to a FatSect for the given index // into the vector. // // Arguments: [iTable] -- index into vector // // Returns: Pointer to CFatSect indicated by index // // History: 27-Dec-91 PhilipLa Created. // // Notes: // //-------------------------------------------------------------------------- inline SCODE CFatVector::GetTable( const FSINDEX iTable, const DWORD dwFlags, CFatSect **ppfs) { SCODE sc; sc = CPagedVector::GetTable(iTable, dwFlags, (void **)ppfs); if (sc == STG_S_NEWPAGE) { (*ppfs)->Init(_csectBlock); } return sc; } //CSEG determines the maximum number of segments that will be //returned by a single Contig call. #define CSEG 32 //+------------------------------------------------------------------------- // // Class: SSegment (seg) // // Purpose: Used for contiguity tables for multi-sector reads and // writes. // // Interface: None. // // History: 16-Aug-91 PhilipLa Created. // // Notes: // //-------------------------------------------------------------------------- struct SSegment { public: ULONG ulOffset; SECT sectStart; ULONG cSect; }; inline SECT SegStart(SSegment seg) { return seg.sectStart; } inline SECT SegEnd(SSegment seg) { return seg.sectStart + seg.cSect - 1; } inline ULONG SegLength(SSegment seg) { return seg.cSect; } inline ULONG SegStartOffset(SSegment seg) { return seg.ulOffset; } inline ULONG SegEndOffset(SSegment seg) { return seg.ulOffset + seg.cSect - 1; } class CMStream; #define GF_READONLY TRUE #define GF_WRITE FALSE class CFat; SAFE_DFBASED_PTR(CBasedFatPtr, CFat); //+---------------------------------------------------------------------- // // Class: CFat (fat) // // Purpose: Main interface to allocation routines // // Interface: Allocate - allocates new chain in the FAT // Extend - Extends an existing FAT chain // GetNext - Returns next sector in a chain // GetSect - Returns nth sector in a chain // GetESect - Returns nth sector in a chain, extending // if necessary // GetLength - Returns the # of sectors in a chain // setup - Initializes for an existing stream // setupnew - Initializes for a new stream // // checksanity - Debugging routine // // History: 18-Jul-91 PhilipLa Created. // 17-Aug-91 PhilipLa Added dirty and full bits // Notes: // //----------------------------------------------------------------------- struct SGetFreeStruct; class CFat { public: CFat(SID sid); CFat(CFat *pfatOld); ~CFat(); VOID Empty(VOID); inline void SetNoScratch(CFat *pfatNoScratch); inline void SetNoSnapshot(SECT sectNoSnapshot); inline SECT GetNoSnapshot(void); inline SECT GetNoSnapshotFree(void); inline void ResetNoSnapshotFree(void); SCODE ResizeNoSnapshot(void); inline SCODE Allocate(ULONG ulSize, SECT *psectFirst); SCODE GetNext(const SECT sect, SECT * psRet); SCODE GetSect( SECT sectStart, ULONG ulOffset, SECT *psectReturn); SCODE GetESect( SECT sectStart, ULONG ulOffset, SECT *psectReturn); SCODE SetNext(SECT sectFirst, SECT sectNext); SCODE GetFree(ULONG ulCount, SECT * sect, BOOL fReadOnly); SCODE GetFreeContig(ULONG ulCount, SSegment STACKBASED *aseg, ULONG cSeg, ULONG *pcSegReturned); SCODE ReserveSects(ULONG cSect); SCODE GetLength(SECT sect, ULONG * pulRet); SCODE SetChainLength(SECT,ULONG); SCODE Init( CMStream *pmsParent, FSINDEX cFatSect, BOOL fConvert); SCODE InitNew(CMStream *pmsParent); void InitCopy(CFat *pfatOld); SCODE InitConvert( CMStream *pmsParent, ULONG cbSize); SCODE InitScratch(CFat *pfat, BOOL fNew); SCODE Remap( SECT sectStart, ULONG oStart, ULONG ulRunLength, SECT *psectOldStart, SECT *psectNewStart, SECT *psectOldEnd, SECT *psectNewEnd); inline SCODE QueryRemapped(const SECT sect); SCODE DirtyAll(); inline SECT GetLast(VOID) const; inline SCODE GetFreeSectCount(ULONG *pcFreeSects); SCODE CountSectType(ULONG * pulRet, SECT sectStart, SECT sectEnd, SECT sectType); inline VOID ResetCopyOnWrite(VOID); inline VOID SetCopyOnWrite(CFat *pfat, SECT sectLast); inline VOID ResetUnmarkedSects(VOID); SCODE FindLast(SECT *psectRet); SCODE FindMaxSect(SECT *psectRet); inline SCODE GetMaxSect(SECT *psectRet); SCODE Contig( SSegment STACKBASED *aseg, BOOL fWrite, SECT sect, ULONG ulLength, ULONG *pcSeg); inline SCODE Flush(VOID); inline void SetParent(CMStream *pms); SCODE Resize(ULONG); inline BOOL IsRangeLocksSector (SECT sect); #if DBG == 1 SCODE checksanity(SECT); void CheckFreeCount(void); #else #define CheckFreeCount() #endif private: inline SCODE IsFree(SECT sect); inline SCODE IsSectType(SECT sect, SECT sectType); inline SCODE MarkSect(SGetFreeStruct *pgf); inline void InitGetFreeStruct(SGetFreeStruct *pgf); inline void ReleaseGetFreeStruct(SGetFreeStruct *pgf); CFatVector _fv; CBasedMStreamPtr _pmsParent; const SID _sid; CBasedFatPtr _pfatReal; CBasedFatPtr _pfatNoScratch; //When committing in no-snapshot mode, all free sectors must // be greater than _sectNoSnapshot. SECT _sectNoSnapshot; SECT _sectNoSnapshotFree; USHORT _uFatShift; USHORT _uFatMask; FSINDEX _cfsTable; ULONG _ulFreeSects; ULONG _cUnmarkedSects; SECT _sectFirstFree; SECT _sectLastUsed; SECT _sectMax; FSINDEX _ipfsRangeLocks; FSOFFSET _isectRangeLocks; SCODE CountFree(ULONG * ulRet); SCODE Extend(SECT,ULONG); inline VOID SectToPair( SECT sect, FSINDEX *pipfs, FSOFFSET *pisect) const; inline SECT PairToSect(FSINDEX ipfs, FSOFFSET isect) const; friend class CDIFat; inline void InitRangeLocksSector (); inline ULONG GetFatVectorLength (); }; inline SECT CFat::GetLast(VOID) const { return _sectLastUsed; } inline SCODE CFat::GetFreeSectCount(ULONG *pcFreeSects) { SCODE sc; if(MAX_ULONG == _ulFreeSects) { msfChk(CountFree(&_ulFreeSects)); } *pcFreeSects = _ulFreeSects; Err: return sc; } inline VOID CFat::ResetCopyOnWrite(VOID) { _sectLastUsed = 0; //Reset _sectFirstFree since this change can conceivably open up // new free sectors before the _sectFirstFree used in COW mode. _ulFreeSects = MAX_ULONG; _sectFirstFree = 0; _sectMax = ENDOFCHAIN; _fv.ResetBits(); _pfatReal = NULL; _cUnmarkedSects = 0; } inline VOID CFat::ResetUnmarkedSects(VOID) { _cUnmarkedSects = 0; CheckFreeCount(); } inline VOID CFat::SetCopyOnWrite(CFat *pfat, SECT sectLast) { msfAssert((_cUnmarkedSects == 0) && aMsg("Unmarked sectors at enter copy-on-write.")); _pfatReal = P_TO_BP(CBasedFatPtr, pfat); _sectLastUsed = sectLast; _sectFirstFree = 0; if (_pfatNoScratch != NULL) { _ulFreeSects = MAX_ULONG; _fv.ResetBits(); } #if DBG == 1 CheckFreeCount(); #endif } inline VOID CFat::SectToPair(SECT sect, FSINDEX *pipfs, FSOFFSET *pisect) const { *pipfs = (FSINDEX)(sect >> _uFatShift); *pisect = (FSOFFSET)(sect & _uFatMask); } inline SECT CFat::PairToSect(FSINDEX ipfs, FSOFFSET isect) const { return (ipfs << _uFatShift) + isect; } inline SCODE CFat::GetMaxSect(SECT *psectRet) { SCODE sc; msfChk(FindMaxSect(&_sectMax)); *psectRet = _sectMax; Err: return sc; } inline SCODE CFat::QueryRemapped(const SECT sect) { SCODE sc = S_FALSE; SECT sectNew; if ((sect == ENDOFCHAIN) || (sect >= _sectLastUsed)) { sc = S_OK; } else { msfChk(_pfatReal->GetNext(sect, §New)); if (sectNew == FREESECT) { sc = S_OK; } else { sc = S_FALSE; } } Err: return sc; } inline void CFat::SetParent(CMStream *pms) { _pmsParent = P_TO_BP(CBasedMStreamPtr, pms); _fv.SetParent(pms); } //+------------------------------------------------------------------------- // // Member: CFat::Flush, public // // Synposis: Write all modified FatSects out to stream // // Effects: Resets all dirty bit fields on FatSects // // Arguments: Void // // Returns: S_OK if call completed OK. // Error code of parent write otherwise. // // Algorithm: Linearly scan through FatSects, writing any sector // that has the dirty bit set. Reset all dirty bits. // // History: 17-Aug-91 PhilipLa Created. // // Notes: // //--------------------------------------------------------------------------- inline SCODE CFat::Flush(VOID) { return _fv.Flush(); } //+------------------------------------------------------------------------- // // Member: CFat::Allocate, public // // Synposis: Allocates a chain within a FAT // // Effects: Modifies a single sector within the fat. Causes a // one sector stream write. // // Arguments: [ulSize] -- Number of sectors to allocate in chain // // Returns: Sector ID of first sector in chain // // Algorithm: Use repetitive calls to GetFree to construct a new chain // // History: 18-Jul-91 PhilipLa Created. // 17-Aug-91 PhilipLa Added dirty bits opt (Dump) // // Notes: // //--------------------------------------------------------------------------- inline SCODE CFat::Allocate(ULONG ulSize, SECT * psectFirst) { return GetFree(ulSize, psectFirst, GF_WRITE); } //+--------------------------------------------------------------------------- // // Member: CFat::SetNoScratch, public // // Synopsis: Set the fat for use in noscratch processing // // Arguments: [pfatNoScratch] -- Pointer to fat to use // // Returns: void // // History: 10-Mar-95 PhilipLa Created // //---------------------------------------------------------------------------- inline void CFat::SetNoScratch(CFat *pfatNoScratch) { _pfatNoScratch = P_TO_BP(CBasedFatPtr, pfatNoScratch); } //+--------------------------------------------------------------------------- // // Member: CFat::SetNoSnapshot, public // // Synopsis: Set the no-snapshot sect marker for commits // // Arguments: [sectNosnapshot] -- Sect to set. // // Returns: void // // History: 18-Oct-95 PhilipLa Created // //---------------------------------------------------------------------------- inline void CFat::SetNoSnapshot(SECT sectNoSnapshot) { _sectNoSnapshot = sectNoSnapshot; if (sectNoSnapshot != 0) { _ulFreeSects = MAX_ULONG; _sectNoSnapshotFree = _sectNoSnapshot; _sectMax = _sectNoSnapshot; #if DBG == 1 SCODE sc; SECT sectLast; msfChk(FindLast(§Last)); msfAssert((_sectMax == sectLast) && aMsg("_sectMax doesn't match actual last sector")); Err: ; #endif } } inline SECT CFat::GetNoSnapshot(void) { return _sectNoSnapshot; } inline SECT CFat::GetNoSnapshotFree(void) { return _sectNoSnapshotFree; } inline void CFat::ResetNoSnapshotFree(void) { _sectNoSnapshotFree = ENDOFCHAIN; } inline void CFat::InitRangeLocksSector () { msfAssert (_uFatShift != 0); const ULONG ulHeaderSize = 1 << (_uFatShift + 2); SECT sect = (OLOCKREGIONEND - ulHeaderSize) >> (_uFatShift + 2); SectToPair(sect, &_ipfsRangeLocks, &_isectRangeLocks); } inline BOOL CFat::IsRangeLocksSector (SECT sect) { FSINDEX ipfs; FSOFFSET isect; SectToPair(sect, &ipfs, &isect); return (ipfs == _ipfsRangeLocks && isect == _isectRangeLocks); } inline ULONG CFat::GetFatVectorLength () { return _cfsTable; } #endif //__FAT_HXX__