⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 compactor.cpp

📁 基于WINCE的文件系统FAL驱动
💻 CPP
📖 第 1 页 / 共 3 页
字号:


START_ERROR:
    return FALSE;
}



/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:       Compactor::GetCompactingBlock()

Description:    Retrieves the ID for the block currently being compacted.

Returns:        Boolean indicating success.
------------------------------------------------------------------------------*/
BOOL Compactor::GetCompactingBlock(PBLOCK_ID pBlockID)
{
    //----- 1. Check the parameters to insure they are legitimate -----
    if(pBlockID == NULL)
    {
        ReportError((TEXT("FLASHDRV.DLL:Compactor::GetCompactingBlockID() - pBlockID == NULL !!!\r\n")));
        return FALSE;
    }

    //----- 2. Return the current block being compacted -----
    *pBlockID = m_compactingBlockID;

    return TRUE;
}



/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:       Compactor::SetCompactingBlock()

Description:    Specifies which block to use for the next compaction process.

Returns:        Boolean indicating success.
------------------------------------------------------------------------------*/
BOOL Compactor::SetCompactingBlock(BLOCK_ID blockID)
{
    m_compactingBlockID = blockID;
    return TRUE;
}


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:       CompactorThread()

Description:    Compactor thread that does the actual work necessary for coalescing
                the dirty, mapped, and free sectors on the media.

Returns:        Boolean indicating success.
------------------------------------------------------------------------------*/
DWORD Compactor::CompactorThread()
{
    DWORD           dwNumDirtySectorsFound  = 0;
    SECTOR_ADDR     physicalSectorAddr      = 0;
    DWORD           Result = FALSE;

    for(;;)
    {
        //----- 1. Wait for the signal to start compaction process -----
        if(WaitForSingleObject(m_hStartCompacting, INFINITE) == WAIT_FAILED)
        {
            DEBUGMSG(ZONE_COMPACTOR, (TEXT("FLASHDRV.DLL:CompactorThread() - Unable to wait on m_hStartCompacting event.  Exiting compactor.\r\n")));
            goto COMPACTOR_EXIT;
        }

        if (m_bEndCompactionThread)
        {
            DEBUGMSG(ZONE_COMPACTOR, (TEXT("FLASHDRV.DLL:CompactorThread() - Exiting compactor.\r\n")));
            Result = TRUE;
            goto COMPACTOR_EXIT;
        }            

        //----- For debugging purposes, print out the statistics for this compaction request
        EnterCriticalSection(&g_csFlashDevice);
        RETAILMSG(1, (TEXT("FLASHDRV.DLL:------------ Starting Compaction... ------------\r\n")));
        RETAILMSG(1, (TEXT("              Looking to recycle %d DIRTY sectors into FREE sectors\r\n"), m_dwFreeSectorsNeeded));
        RETAILMSG(1, (TEXT("              >>> Media State Information: >>>\r\n")));
        RETAILMSG(1, (TEXT("                 Free  Sectors = %d\r\n"), m_pSectorMgr->GetNumberOfFreeSectors() )); 
        RETAILMSG(1, (TEXT("                 Dirty Sectors = %d\r\n"), m_pSectorMgr->GetNumDirtySectors() )); 
        RETAILMSG(1, (TEXT("FLASHDRV.DLL:------------------------------------------------\r\n")));
        LeaveCriticalSection(&g_csFlashDevice);

        for(;;)
        {
            DWORD dwStatus = 0;
            DWORD dwBlkCount = 0;
        
            EnterCriticalSection(&g_csFlashDevice);

            //----- 2. Are we done with this compaction process? Compaction is over if the number of -----
            //         requested free sectors have been reclaimed or there are no more DIRTY sectors
            //         left to recycle.
            if((m_dwFreeSectorsNeeded == 0) || (m_pSectorMgr->GetNumDirtySectors() == 0) )
            {
                LeaveCriticalSection( &g_csFlashDevice);
                break;
            }

            //----- 3. Compact the next block... -----
            m_compactingBlockID = GetNextCompactionBlock(m_compactingBlockID);

            if ((dwBlkCount >= m_pRegion->dwNumPhysBlocks) || (m_compactingBlockID == INVALID_BLOCK_ID))
            {
                RETAILMSG(1, (TEXT("FLASHDRV.DLL:CompactorThread() - CompactorThread(0x%x) failed; unable to compact!!!\r\n"), m_compactingBlockID));
                LeaveCriticalSection( &g_csFlashDevice);
                goto COMPACTOR_EXIT;
            }                

            //----- For debugging purposes, print out the compaction block information... -----
            DEBUGMSG(ZONE_COMPACTOR, (TEXT("FLASHDRV.DLL:CompactorThread() - Compacting BLOCK %d\r\n"), m_compactingBlockID));

            //----- 5. Compact the current block... -----
            if((dwNumDirtySectorsFound = CompactBlock(m_compactingBlockID, USE_SECTOR_MAPPING_INFO)) == BLOCK_COMPACTION_ERROR)
            {
                ReportError((TEXT("FLASHDRV.DLL:CompactorThread() - Compactor::CompactBlock(%d) failed; unable to compact!!!\r\n"), m_compactingBlockID));
                LeaveCriticalSection( &g_csFlashDevice);
                break;
            }

            //----- 7. Update the number of DIRTY sectors recycled into FREE sectors while compacting this block -----
            if(m_dwFreeSectorsNeeded < dwNumDirtySectorsFound)
            {
                m_dwFreeSectorsNeeded = 0;                              // Done compacting...
            }else
            {
                m_dwFreeSectorsNeeded -= dwNumDirtySectorsFound;        // Subtract # of recycled DIRTY sectors and keep going...
            }

            LeaveCriticalSection( &g_csFlashDevice);
        }
    
        //----- For debugging purposes, print out the compaction block information... -----
        DEBUGMSG(ZONE_COMPACTOR, (TEXT("FLASHDRV.DLL   >>> Compaction process complete: %d DIRTY sectors recycled \r\n"), dwNumDirtySectorsFound));     


        //----- 9. Signal that the compaction operation is complete... -----
        if(!SetEvent(m_hCompactionComplete))
        {
            ReportError((TEXT("FLASHDRV.DLL:CompactorThread() - Unable to signal compaction is complete!!!\r\n")));
            goto COMPACTOR_EXIT;
        }       

    }

COMPACTOR_EXIT:
    return Result;
}



/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:       Compactor::CompactBlock()

Description:    Compacts the specified block.  Data in MAPPED sectors are relocated 
                to another part of the media (using the Sector Manager) and DIRTY
                sectors are recycled into FREE sectors.

Notes:          The treatAsDirtySectorAddr parameter is used to indicate a single
                sector in the block that should be treated as DIRTY regardless of
                what the mapping information states.  Practically, this situation
                only occurs when we are trying to re-map data to a new sector on the
                media and we are NOT able to mark the old data as DIRTY.  In this case,
                we need to compact this block and treat the data in this sector as 
                DIRTY.  Once compaction is complete, the old data will be deleted
                from the media and recycled into a FREE sector.

                Setting treatAsDirtySectorAddr == USE_SECTOR_MAPPING_INFO indicates that
                the sector mapping information should be used and no sectors need to
                explicitly be treated as DIRTY.

Returns:        Number of DIRTY sectors recycled into FREE sectors.
------------------------------------------------------------------------------*/
DWORD Compactor::CompactBlock(BLOCK_ID compactionBlockID, SECTOR_ADDR treatAsDirtySectorAddr)
{
    SECTOR_ADDR         newPhysicalSectorAddr   = 0;
    SECTOR_ADDR         physicalSectorAddr      = 0;

    DWORD               dwNumDirtySectorsFound  = 0;
    DWORD               i                       = 0;
    SectorMappingInfo sectorMappingInfo;    

    // Record compaction in CELOG
    CELOG_CompactBlock(m_bCritical, compactionBlockID);

    //----- 1. Determine starting physical sector address for the specified block being compacted -----
    //         NOTE: If # of sectors/block is a power of 2, we can avoid a potentially expensive multiplication 
    //         (Refer to Compactor::InitCompactor() for details...)
    physicalSectorAddr = m_pSectorMgr->GetStartSectorInBlock (compactionBlockID);

    // Unmark any sectors in this block that are free, since all of the sectors will be marked
    // free at the end of this operation
    m_pSectorMgr->UnmarkSectorsAsFree(physicalSectorAddr, m_pRegion->dwSectorsPerBlock);

    //----- 2. Compact the specified block.  If any data is still MAPPED, move it... -----
    dwNumDirtySectorsFound = 0;
    for(i=0; i<m_pRegion->dwSectorsPerBlock; i++, physicalSectorAddr++)
    {
        //----- 3. Read the sector mapping information for the current physical sector -----
        if(!FMD.pReadSector(physicalSectorAddr, NULL, (PSectorInfo)&sectorMappingInfo, 1))
        {
            ReportError((TEXT("FLASHDRV.DLL:Compactor::CompactBlock() - Unable to read sector mapping info for physical sector 0x%08x\r\n"), physicalSectorAddr));
            goto COMPACTION_ERROR;
        }

        //----- 4. DIRTY sector?  Unmark this sector as DIRTY (using the Sector Manager) because -----
        //         we are going to recycle it into a FREE sector through an erase operation.
        if( IsSectorDirty(sectorMappingInfo) || 
           ((treatAsDirtySectorAddr != USE_SECTOR_MAPPING_INFO) && (treatAsDirtySectorAddr == physicalSectorAddr))
          )
        {
            //----- For debugging purposes, print out the state of this sector -----
            DEBUGMSG(ZONE_COMPACTOR, (TEXT("FLASHDRV.DLL     >>> Physical sector 0x%08x is DIRTY\r\n"), physicalSectorAddr));       

            if(!m_pSectorMgr->UnmarkSectorsAsDirty(physicalSectorAddr, 1))
            {
                ReportError((TEXT("FLASHDRV.DLL:Compactor::CompactBlock() - Unable to unmark physical sector 0x%08x as DIRTY\r\n"), physicalSectorAddr));
            }
            dwNumDirtySectorsFound++;
            continue;
        }

        //----- 5. Data is MAPPED.  Move it to another free sector on the FLASH media -----
        if(IsSectorMapped(sectorMappingInfo))
        {
            //----- For debugging purposes, print out the state of this sector -----
            DEBUGMSG(ZONE_COMPACTOR, (TEXT("FLASHDRV.DLL     >>> Physical sector 0x%08x is MAPPED\r\n"), physicalSectorAddr));      

            // Should check if LSA is valid or not before copying the sector
            // to avoid that all blocks have this invalid sector by the Compactor.
            if(!m_pMap->IsValidLogicalSector(sectorMappingInfo.logicalSectorAddr))
            {
                ReportError((TEXT("FLASHDRV.DLL     >>> Logical sector(=0x%08x) of physical sector(=0x%08x) is incorrect.\r\n"), sectorMappingInfo.logicalSectorAddr, physicalSectorAddr));
                goto COMPACTION_ERROR;
            }

            //----- 6. Read the data into a temporary buffer -----
            if(!FMD.pReadSector(physicalSectorAddr, m_pSectorData, NULL, 1))
            {
                ReportError((TEXT("FLASHDRV.DLL:Compactor::CompactBlock() - Unable to read sector data for physical sector 0x%08x\r\n"), physicalSectorAddr));
                goto COMPACTION_ERROR;
            }

            //----- Write the sector data to the media.  Notice that this operation is repetitively -----
            //      tried ONLY if FMD.pWriteSector() fails.  Unless the FLASH block we are writing to
            //      has just gone bad, this loop will only execute once.
            for(;;)
            {
                //----- 7. Get a free physical sector to store the data into -----
                //         NOTE: Notice that the second parameter is TRUE; this forces the Sector Manager
                //               to give us the next FREE sector regardless of how many are left.  This is
                //               important so that this call to the Sector Manager doesn't trigger another
                //               compaction.
                if(!m_pSectorMgr->GetNextFreeSector(&newPhysicalSectorAddr, TRUE))
                {
                    ReportError((TEXT("FLASHDRV.DLL:Compactor::CompactBlock() - Unable to get next free physical sector address for writing!  The media is FULL\r\n")));
                    goto COMPACTION_ERROR;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -