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;
}
Ejemplo n.º 2
0
int GDALRasterBlock::FlushCacheBlock( int bDirtyBlocksOnly )

{
    GDALRasterBlock *poTarget;

    {
        INITIALIZE_LOCK;
        poTarget = poOldest;

        while( poTarget != NULL )
        {
            if( !bDirtyBlocksOnly || poTarget->GetDirty() )
            {
                if( CPLAtomicCompareAndExchange(
                        &(poTarget->nLockCount), 0, -1) )
                    break;
            }
            poTarget = poTarget->poPrevious;
        }

        if( poTarget == NULL )
            return FALSE;
        if( bSleepsForBockCacheDebug )
            CPLSleep(CPLAtof(
                CPLGetConfigOption(
                    "GDAL_RB_FLUSHBLOCK_SLEEP_AFTER_DROP_LOCK", "0")));

        poTarget->Detach_unlocked();
        poTarget->GetBand()->UnreferenceBlock(poTarget);
    }

    if( bSleepsForBockCacheDebug )
        CPLSleep(CPLAtof(
            CPLGetConfigOption("GDAL_RB_FLUSHBLOCK_SLEEP_AFTER_RB_LOCK", "0")));

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

    VSIFree(poTarget->pData);
    poTarget->pData = NULL;
    poTarget->GetBand()->AddBlockToFreeList(poTarget);

    return TRUE;
}
Ejemplo n.º 3
0
CPLErr GDALHashSetBandBlockCache::FlushBlock( int nXBlockOff, int nYBlockOff,
                                              int bWriteDirtyBlock )

{
    GDALRasterBlock oBlockForLookup(nXBlockOff, nYBlockOff);
    GDALRasterBlock* poBlock = nullptr;
    {
        CPLLockHolderOptionalLockD( hLock );
        auto oIter = m_oSet.find(&oBlockForLookup);
        if( oIter == m_oSet.end() )
            return CE_None;
        poBlock = *oIter;
        m_oSet.erase(oIter);
    }

    if( !poBlock->DropLockForRemovalFromStorage() )
        return CE_None;

    CPLErr eErr = CE_None;

    if( bWriteDirtyBlock && poBlock->GetDirty() )
        eErr = poBlock->Write();

    delete poBlock;

    return eErr;
}
Ejemplo n.º 4
0
CPLErr GDALArrayBandBlockCache::FlushBlock( int nXBlockOff, int nYBlockOff,
                                             int bWriteDirtyBlock )

{
    int             nBlockIndex;
    GDALRasterBlock *poBlock = NULL;

/* -------------------------------------------------------------------- */
/*      Simple case for single level caches.                            */
/* -------------------------------------------------------------------- */
    if( !bSubBlockingActive )
    {
        nBlockIndex = nXBlockOff + nYBlockOff * poBand->nBlocksPerRow;

        poBlock = u.papoBlocks[nBlockIndex];
        u.papoBlocks[nBlockIndex] = NULL;
    }

/* -------------------------------------------------------------------- */
/*      Identify our subblock.                                          */
/* -------------------------------------------------------------------- */
    else
    {
        int nSubBlock = TO_SUBBLOCK(nXBlockOff) 
            + TO_SUBBLOCK(nYBlockOff) * nSubBlocksPerRow;
        
/* -------------------------------------------------------------------- */
/*      Check within subblock.                                          */
/* -------------------------------------------------------------------- */
        GDALRasterBlock **papoSubBlockGrid =  u.papapoBlocks[nSubBlock];
        if( papoSubBlockGrid == NULL )
            return CE_None;

        int nBlockInSubBlock = WITHIN_SUBBLOCK(nXBlockOff)
            + WITHIN_SUBBLOCK(nYBlockOff) * SUBBLOCK_SIZE;

        poBlock = papoSubBlockGrid[nBlockInSubBlock];
        papoSubBlockGrid[nBlockInSubBlock] = NULL;
    }

    if( poBlock == NULL )
        return CE_None;

    if( !poBlock->DropLockForRemovalFromStorage() )
        return CE_None;

/* -------------------------------------------------------------------- */
/*      Is the target block dirty?  If so we need to write it.          */
/* -------------------------------------------------------------------- */
    CPLErr eErr = CE_None;

    poBlock->Detach();

    if( bWriteDirtyBlock && poBlock->GetDirty() )
        eErr = poBlock->Write();

/* -------------------------------------------------------------------- */
/*      Deallocate the block;                                           */
/* -------------------------------------------------------------------- */
    delete poBlock;

    return eErr;
}
Ejemplo n.º 5
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 );
}
Ejemplo n.º 6
0
CPLErr GDALRasterBlock::Internalize()

{
    CPLAssert( pData == NULL );

    void        *pNewData = NULL;

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

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

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

            if( bFirstIter )
                nCacheUsed += nSizeInBytes;
            GDALRasterBlock *poTarget = poOldest;
            while( nCacheUsed > nCurCacheMax )
            {
                while( poTarget != NULL )
                {
                    if( CPLAtomicCompareAndExchange(
                            &(poTarget->nLockCount), 0, -1) )
                        break;
                    poTarget = poTarget->poPrevious;
                }

                if( poTarget != NULL )
                {
                    if( bSleepsForBockCacheDebug )
                        CPLSleep(CPLAtof(
                            CPLGetConfigOption(
                                "GDAL_RB_INTERNALIZE_SLEEP_AFTER_DROP_LOCK",
                                "0")));

                    GDALRasterBlock* _poPrevious = poTarget->poPrevious;

                    poTarget->Detach_unlocked();
                    poTarget->GetBand()->UnreferenceBlock(poTarget);

                    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 )
                    {
                        bLoopAgain = ( nCacheUsed > nCurCacheMax );
                        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 * const 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;
            }
            else
            {
                VSIFree(poBlock->pData);
            }
            poBlock->pData = NULL;

            poBlock->GetBand()->AddBlockToFreeList(poBlock);
        }
    }
    while(bLoopAgain);

    if( pNewData == NULL )
    {
        pNewData = VSI_MALLOC_VERBOSE( nSizeInBytes );
        if( pNewData == NULL )
        {
            return( CE_Failure );
        }
    }

    pData = pNewData;

    return CE_None;
}