Ejemplo n.º 1
0
int GDALRasterBlock::FlushCacheBlock(int bDirtyBlocksOnly)

{
    GDALRasterBlock *poTarget;

    {
        INITIALIZE_LOCK;
        poTarget = poOldest;

        while( poTarget != NULL && (poTarget->GetLockCount() > 0 ||
                                    (bDirtyBlocksOnly && !poTarget->GetDirty())) )
            poTarget = poTarget->poPrevious;

        if( poTarget == NULL )
            return FALSE;

        poTarget->Detach_unlocked();
        poTarget->GetBand()->UnreferenceBlock(poTarget->GetXOff(),poTarget->GetYOff());
    }

    if( poTarget->GetDirty() )
    {
        CPLErr eErr = poTarget->Write();
        if( eErr != CE_None )
        {
            /* Save the error for later reporting */
            poTarget->GetBand()->SetFlushBlockErr(eErr);
        }
    }
    delete poTarget;

    return TRUE;
}
int GDALRasterBlock::FlushCacheBlock()

{
    int nXOff, nYOff;
    GDALRasterBand *poBand;

    {
        CPLMutexHolderD( &hRBMutex );
        GDALRasterBlock *poTarget = (GDALRasterBlock *) poOldest;

        while( poTarget != NULL && poTarget->GetLockCount() > 0 ) 
            poTarget = poTarget->poPrevious;
        
        if( poTarget == NULL )
            return FALSE;

        poTarget->Detach();

        nXOff = poTarget->GetXOff();
        nYOff = poTarget->GetYOff();
        poBand = poTarget->GetBand();
    }

    CPLErr eErr = poBand->FlushBlock( nXOff, nYOff );
    if (eErr != CE_None)
    {
        /* Save the error for later reporting */
        poBand->SetFlushBlockErr(eErr);
    }

    return TRUE;
}
Ejemplo n.º 3
0
CPLErr GDALRasterBlock::Internalize()

{
    void        *pNewData = NULL;
    int         nSizeInBytes;

    CPLAssert( pData == NULL );

    // This call will initialize the hRBLock mutex. Other call places can
    // only be called if we have go through there.
    GIntBig     nCurCacheMax = GDALGetCacheMax64();

    /* No risk of overflow as it is checked in GDALRasterBand::InitBlockInfo() */
    nSizeInBytes = GetBlockSize();

    /* -------------------------------------------------------------------- */
    /*      Flush old blocks if we are nearing our memory limit.            */
    /* -------------------------------------------------------------------- */
    int bFirstIter = TRUE;
    int bLoopAgain;
    do
    {
        bLoopAgain = FALSE;
        GDALRasterBlock* apoBlocksToFree[64];
        int nBlocksToFree = 0;
        {
            TAKE_LOCK;

            if( bFirstIter )
                nCacheUsed += nSizeInBytes;
            GDALRasterBlock *poTarget = poOldest;
            while( nCacheUsed > nCurCacheMax )
            {
                while( poTarget != NULL && poTarget->GetLockCount() > 0 )
                    poTarget = poTarget->poPrevious;

                if( poTarget != NULL )
                {
                    GDALRasterBlock* _poPrevious = poTarget->poPrevious;

                    poTarget->Detach_unlocked();
                    poTarget->GetBand()->UnreferenceBlock(poTarget->GetXOff(),poTarget->GetYOff());

                    apoBlocksToFree[nBlocksToFree++] = poTarget;
                    if( poTarget->GetDirty() )
                    {
                        // Only free one dirty block at a time so that
                        // other dirty blocks of other bands with the same coordinates
                        // can be found with TryGetLockedBlock()
                        bLoopAgain = ( nCacheUsed > nCurCacheMax );
                        break;
                    }
                    if( nBlocksToFree == 64 )
                    {
                        CPLDebug("GDAL", "More than 64 blocks are flagged to be flushed. Not trying more");
                        break;
                    }

                    poTarget = _poPrevious;
                }
                else
                    break;
            }

            /* -------------------------------------------------------------------- */
            /*      Add this block to the list.                                     */
            /* -------------------------------------------------------------------- */
            if( !bLoopAgain )
                Touch_unlocked();
        }

        bFirstIter = FALSE;

        /* Now free blocks we have detached and removed from their band */
        for(int i=0; i<nBlocksToFree; i++)
        {
            GDALRasterBlock *poBlock = apoBlocksToFree[i];

            if( poBlock->GetDirty() )
            {
                CPLErr eErr = poBlock->Write();
                if( eErr != CE_None )
                {
                    /* Save the error for later reporting */
                    poBlock->GetBand()->SetFlushBlockErr(eErr);
                }
            }

            /* Try to recycle the data of an existing block */
            void* pDataBlock = poBlock->pData;
            if( pNewData == NULL && pDataBlock != NULL &&
                    poBlock->GetBlockSize() >= nSizeInBytes )
            {
                pNewData = pDataBlock;
                poBlock->pData = NULL;
            }

            delete poBlock;
        }
    }
    while(bLoopAgain);

    if( pNewData == NULL )
    {
        pNewData = VSIMalloc( nSizeInBytes );
        if( pNewData == NULL )
        {
            CPLError( CE_Failure, CPLE_OutOfMemory,
                      "GDALRasterBlock::Internalize : Out of memory allocating %d bytes.",
                      nSizeInBytes);
            return( CE_Failure );
        }
    }

    pData = pNewData;

    return( CE_None );
}