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; }
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 ); }