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

📄 compactor.cpp

📁 基于WINCE的文件系统FAL驱动
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

Module Name:    COMPACTOR.C

Abstract:       Compactor module

Notes:          The following module is responsible for compacting the FLASH media blocks.
                A compaction operation works as follows (using psuedo-code):
                 
                   foreach(physicalSector in Block b)
                   {
                        if(IsSectorMapped(physicalSector))
                        {
                            ReadSectorData(physicalSector, buffer);
                            newPhysicalSectorAddr = SM_GetNextFreeSector();
                            WriteSectorData(newPhysicalSector, buffer);
                            UpdateLogicalToPhysicalMapping(logicalSectorAddr, newPhysicalSectorAddr);   
                            MarkSectorDirty(physicalSector);
                        }

                        if(IsSectorDirty(physicalSector)
                        {
                            dwNumDirtySectorsFound++;
                        }
                    }
                    EraseBlock(Block b);
                    AddFreeSectorsToSectorManager(Block b);

                That is, to compact a block we just need to move any good data to another physical location 
                on the media and simply ignore any DIRTY physical sectors.  Once the entire block has been 
                processed, it can then safely be erased.  Notice also that all of the good data is still 
                retained after the ERASE operation and that data CANNOT be lost during a power-failure situation 
                because the old data is marked DIRTY after the data has been safely moved to another physical 
                sector address.   

                There are several important points to consider in this algorithm:

                    1)  The compactor uses the *exact* same code to move good data to another portion of the 
                        FLASH media as the FAL uses to write new data from the file system.  Practically, this 
                        means that the compactor queries the Sector Manager for the next FREE physical sector 
                        when it needs to perform a WRITE operation.

                    2)  The algorithm takes the necessary precautions to avoid *any* data loss during a 
                        power-failure condition.  In the worst case scenario, the FLASH media will end up with 
                        two separate physical copies of the SAME data, which will be cleaned up by the FAL during 
                        the next boot sequence.

                    3)  The algorithm is simple.  Notice that there are NO special situations or end cases to consider.  
                        The Compactor simply moves good data to another potion of the disk (a.k.a. compacting the data) 
                        and then erases the block.
                        
                The Compactor *always* processes FLASH blocks consecutively.  Once the Compactor reaches the last 
                FLASH block on the media, it simply moves back to the first FLASH block and continues as necessary.

-----------------------------------------------------------------------------*/

#include "compactor.h"


//#undef ZONE_COMPACTOR
//#define ZONE_COMPACTOR 1
//#undef DEBUGMSG
//#define DEBUGMSG(cond,msg) RETAILMSG(cond,msg)

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

Description:    Initializes the compactor. 

Notes:          The compactor is not started by default.  The caller must invoke
                Compactor::StartCompactor() to start the compactor thread.

Returns:        Boolean indicating success.
------------------------------------------------------------------------------*/
BOOL Compactor::Init(PFlashRegion pRegion, FileSysFal* pFal)
{
    m_pRegion = pRegion;
    m_pFal = pFal;
    m_pSectorMgr = pFal->m_pSectorMgr;
    m_pMap = pFal->m_pMap;
    m_compactingBlockID = pRegion->dwStartPhysBlock;
    m_bEndCompactionThread = FALSE;

    if (pRegion->dwCompactBlocks < MINIMUM_FLASH_BLOCKS_TO_RESERVE)
    {
        ReportError((TEXT("FLASHDRV.DLL:Compactor::InitCompactor() - Invalid number of compaction blocks in region.\r\n")));
        goto INIT_ERROR;
    }
    
    //----- 1. Create the event that controls the compactor -----
    if((m_hStartCompacting = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL)
    {
        ReportError((TEXT("FLASHDRV.DLL:Compactor::InitCompactor() - Unable to create compactor control event object!!!\r\n")));
        goto INIT_ERROR;
    }

    //----- 2. Create the event that signals when compacting is complete -----
    if((m_hCompactionComplete = CreateEvent(NULL, FALSE, FALSE, NULL)) == NULL)
    {
        ReportError((TEXT("FLASHDRV.DLL:Compactor::InitCompactor() - Unable to create compactor completion event object!!!\r\n")));
        goto INIT_ERROR;
    }


    //----- 4. Allocate a buffer to use for moving MAPPED data during a compaction -----
    if((m_pSectorData = (PBYTE)LocalAlloc(LMEM_FIXED, g_pFlashMediaInfo->dwDataBytesPerSector)) == NULL)
    {
        ReportError((TEXT("FLASHDRV.DLL:Compactor::InitCompactor() - Unable to allocate memory for sector data.\r\n")));
        goto INIT_ERROR;
    }

    //----- 5. Initialize the "nested compactions" counter.  This counter is used to prevent an infinite -----
    //         recursion situation that can occur if WRITE operations keep failing within Compactor::CompactBlock()
    m_dwNestedCompactions = 0;

    //----- 6. Retrieve the ID for the block that we need to process on the next compaction -----
    //         NOTE: Currently, the FAL computes the block ID during system initialization and
    //               calls Compactor::SetCompactingBlock() appropriately.  Hence, we don't need to explicitly
    //               store/retrieve this state information on the FLASH media.


    //----- 7. Create the compactor thread -----
    if((m_hCompactorThread = CreateThread(NULL, 0, ::CompactorThread, (LPVOID)this, 0, &m_dwThreadID)) == NULL)
    {
        ReportError((TEXT("FLASHDRV.DLL:Compactor::InitCompactor() - Unable to create compactor thread!!!\r\n")));
        goto INIT_ERROR;
    }

    return TRUE;

INIT_ERROR:
    CloseHandle(m_hStartCompacting);
    CloseHandle(m_hCompactionComplete);
    CloseHandle(m_hCompactorThread);
    return FALSE;
}


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

Description:    Deinitializes the compactor. 

Notes:          The compactor is first stopped.

Returns:        Boolean indicating success.
------------------------------------------------------------------------------*/
BOOL Compactor::Deinit()
{
    // By entering the device critical section, we are ensuring the current compaction 
    // operation is complete
    EnterCriticalSection(&g_csFlashDevice);
    
    m_dwFreeSectorsNeeded = 0;
    m_bEndCompactionThread = TRUE;
    SetEvent (m_hStartCompacting);
    
    LeaveCriticalSection(&g_csFlashDevice);

    WaitForSingleObject(m_hCompactorThread, 10000);
    
    //----- 2. Free all the compactor thread's system resources -----
    if(LocalFree(m_pSectorData) != NULL)
    {
        ReportError((TEXT("FLASHDRV.DLL:Compactor::Deinit() - Unable to free buffer used for moving MAPPED data\r\n")));
    }
    
    CloseHandle(m_hCompactionComplete);
    CloseHandle(m_hStartCompacting);
    CloseHandle(m_hCompactorThread);
    return TRUE;
}


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

Description:    Starts the compactor using the specified thread priority.  The
                compactor thread then attempts to find the the specified number 
                of free sectors.  If bCritical == TRUE, this function doesn't
                return until the compaction stage completes.

Returns:        Boolean indicating success.
------------------------------------------------------------------------------*/
BOOL Compactor::StartCompactor(DWORD dwPriority, DWORD dwFreeSectorsNeeded, BOOL bCritical)
{

    //----- 1. Are there enough DIRTY sectors on the media to fulfill this request? -----
    if(dwFreeSectorsNeeded > m_pSectorMgr->GetNumDirtySectors())
    {
        if(m_pSectorMgr->GetNumDirtySectors() == 0)
        {
            ReportError((TEXT("FLASHDRV.DLL:Compactor::StartCompactor() - There aren't any DIRTY sectors left; the compactor can't be started\r\n")));
            goto START_ERROR;
        }else{
            // Set this compaction operation to retrieve the rest of the DIRTY sectors...
            dwFreeSectorsNeeded = m_pSectorMgr->GetNumDirtySectors();
        }
    }

    //----- 2. Set the number of DIRTY sectors to recycle into FREE sectors -----
    m_dwFreeSectorsNeeded = dwFreeSectorsNeeded;

    m_bCritical = bCritical;

    //----- 3. If this is a critical compaction, make sure the "compaction completed" wait event is reset -----
    if(bCritical == TRUE)
    {
        if(!ResetEvent(m_hCompactionComplete))
        {
            ReportError((TEXT("FLASHDRV.DLL:Compactor::StartCompactor() - Unable to reset the critical Compaction Complete wait event!!!\r\n")));
            goto START_ERROR;
        }
    }

    //----- 4. Signal the compactor to start retrieving the requested number of sectors -----
    if(!SetEvent(m_hStartCompacting))
    {
        ReportError((TEXT("FLASHDRV.DLL:Compactor::StartCompactor() - Unable to signal compactor thread!!!\r\n")));
        goto START_ERROR;
    }

    //----- 5. Set the thread priority accordingly -----
    if(!CeSetThreadPriority(m_hCompactorThread, dwPriority))
    {
        ReportError((TEXT("FLASHDRV.DLL:Compactor::StartCompactor() - Unable to set compactor's thread priority!!!\r\n")));
        goto START_ERROR;
    }

    //----- 6. SPECIAL CASE: If this is a CRITICAL compaction request, we must wait for the compaction process -----
    //                       to complete before returning (this compaction is then SYNCHRONOUSLY executed for the caller).
    if(bCritical == TRUE)
    {
        LeaveCriticalSection( &g_csFlashDevice);

        if(WaitForSingleObject(m_hCompactionComplete, INFINITE) == WAIT_FAILED)
        {
            ReportError((TEXT("FLASHDRV.DLL:CompactorThread() - Unable to wait on m_hCompactionComplete event!\r\n")));
            EnterCriticalSection( &g_csFlashDevice);
            goto START_ERROR;
        }
        EnterCriticalSection( &g_csFlashDevice);
    }
    return TRUE;

⌨️ 快捷键说明

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