LCOV - code coverage report
Current view: directory - gcore - gdalrasterblock.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 170 130 76.5 %
Date: 2012-12-26 Functions: 21 15 71.4 %

       1                 : /******************************************************************************
       2                 :  * $Id: gdalrasterblock.cpp 24412 2012-05-14 17:55:36Z rouault $
       3                 :  *
       4                 :  * Project:  GDAL Core
       5                 :  * Purpose:  Implementation of GDALRasterBlock class and related global 
       6                 :  *           raster block cache management.
       7                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       8                 :  *
       9                 :  **********************************************************************
      10                 :  * Copyright (c) 1998, Frank Warmerdam <warmerdam@pobox.com>
      11                 :  *
      12                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      13                 :  * copy of this software and associated documentation files (the "Software"),
      14                 :  * to deal in the Software without restriction, including without limitation
      15                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      16                 :  * and/or sell copies of the Software, and to permit persons to whom the
      17                 :  * Software is furnished to do so, subject to the following conditions:
      18                 :  *
      19                 :  * The above copyright notice and this permission notice shall be included
      20                 :  * in all copies or substantial portions of the Software.
      21                 :  *
      22                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      23                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      24                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      25                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      26                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      27                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      28                 :  * DEALINGS IN THE SOFTWARE.
      29                 :  ****************************************************************************/
      30                 : 
      31                 : #include "gdal_priv.h"
      32                 : #include "cpl_multiproc.h"
      33                 : 
      34                 : CPL_CVSID("$Id: gdalrasterblock.cpp 24412 2012-05-14 17:55:36Z rouault $");
      35                 : 
      36                 : static int bCacheMaxInitialized = FALSE;
      37                 : static GIntBig nCacheMax = 40 * 1024*1024;
      38                 : static volatile GIntBig nCacheUsed = 0;
      39                 : 
      40                 : static volatile GDALRasterBlock *poOldest = NULL;    /* tail */
      41                 : static volatile GDALRasterBlock *poNewest = NULL;    /* head */
      42                 : 
      43                 : static void *hRBMutex = NULL;
      44                 : 
      45                 : 
      46                 : /************************************************************************/
      47                 : /*                          GDALSetCacheMax()                           */
      48                 : /************************************************************************/
      49                 : 
      50                 : /**
      51                 :  * \brief Set maximum cache memory.
      52                 :  *
      53                 :  * This function sets the maximum amount of memory that GDAL is permitted
      54                 :  * to use for GDALRasterBlock caching. The unit of the value is bytes.
      55                 :  *
      56                 :  * The maximum value is 2GB, due to the use of a signed 32 bit integer.
      57                 :  * Use GDALSetCacheMax64() to be able to set a higher value.
      58                 :  *
      59                 :  * @param nNewSizeInBytes the maximum number of bytes for caching.
      60                 :  */
      61                 : 
      62               8 : void CPL_STDCALL GDALSetCacheMax( int nNewSizeInBytes )
      63                 : 
      64                 : {
      65               8 :     GDALSetCacheMax64(nNewSizeInBytes);
      66               8 : }
      67                 : 
      68                 : 
      69                 : /************************************************************************/
      70                 : /*                        GDALSetCacheMax64()                           */
      71                 : /************************************************************************/
      72                 : 
      73                 : /**
      74                 :  * \brief Set maximum cache memory.
      75                 :  *
      76                 :  * This function sets the maximum amount of memory that GDAL is permitted
      77                 :  * to use for GDALRasterBlock caching. The unit of the value is bytes.
      78                 :  *
      79                 :  * Note: On 32 bit platforms, the maximum amount of memory that can be addressed
      80                 :  * by a process might be 2 GB or 3 GB, depending on the operating system
      81                 :  * capabilities. This function will not make any attempt to check the
      82                 :  * consistency of the passed value with the effective capabilities of the OS.
      83                 :  *
      84                 :  * @param nNewSizeInBytes the maximum number of bytes for caching.
      85                 :  *
      86                 :  * @since GDAL 1.8.0
      87                 :  */
      88                 : 
      89              20 : void CPL_STDCALL GDALSetCacheMax64( GIntBig nNewSizeInBytes )
      90                 : 
      91                 : {
      92              20 :     bCacheMaxInitialized = TRUE;
      93              20 :     nCacheMax = nNewSizeInBytes;
      94                 : 
      95                 : /* -------------------------------------------------------------------- */
      96                 : /*      Flush blocks till we are under the new limit or till we         */
      97                 : /*      can't seem to flush anymore.                                    */
      98                 : /* -------------------------------------------------------------------- */
      99              44 :     while( nCacheUsed > nCacheMax )
     100                 :     {
     101               4 :         GIntBig nOldCacheUsed = nCacheUsed;
     102                 : 
     103               4 :         GDALFlushCacheBlock();
     104                 : 
     105               4 :         if( nCacheUsed == nOldCacheUsed )
     106               0 :             break;
     107                 :     }
     108              20 : }
     109                 : 
     110                 : /************************************************************************/
     111                 : /*                          GDALGetCacheMax()                           */
     112                 : /************************************************************************/
     113                 : 
     114                 : /**
     115                 :  * \brief Get maximum cache memory.
     116                 :  *
     117                 :  * Gets the maximum amount of memory available to the GDALRasterBlock
     118                 :  * caching system for caching GDAL read/write imagery.
     119                 :  *
     120                 :  * The first type this function is called, it will read the GDAL_CACHEMAX
     121                 :  * configuation option to initialize the maximum cache memory.
     122                 :  *
     123                 :  * This function cannot return a value higher than 2 GB. Use
     124                 :  * GDALGetCacheMax64() to get a non-truncated value.
     125                 :  *
     126                 :  * @return maximum in bytes. 
     127                 :  */
     128                 : 
     129               0 : int CPL_STDCALL GDALGetCacheMax()
     130                 : {
     131               0 :     GIntBig nRes = GDALGetCacheMax64();
     132               0 :     if (nRes > INT_MAX)
     133                 :     {
     134                 :         static int bHasWarned = FALSE;
     135               0 :         if (!bHasWarned)
     136                 :         {
     137                 :             CPLError(CE_Warning, CPLE_AppDefined,
     138                 :                      "Cache max value doesn't fit on a 32 bit integer. "
     139               0 :                      "Call GDALGetCacheMax64() instead");
     140               0 :             bHasWarned = TRUE;
     141                 :         }
     142               0 :         nRes = INT_MAX;
     143                 :     }
     144               0 :     return (int)nRes;
     145                 : }
     146                 : 
     147                 : /************************************************************************/
     148                 : /*                         GDALGetCacheMax64()                          */
     149                 : /************************************************************************/
     150                 : 
     151                 : /**
     152                 :  * \brief Get maximum cache memory.
     153                 :  *
     154                 :  * Gets the maximum amount of memory available to the GDALRasterBlock
     155                 :  * caching system for caching GDAL read/write imagery.
     156                 :  *
     157                 :  * The first type this function is called, it will read the GDAL_CACHEMAX
     158                 :  * configuation option to initialize the maximum cache memory.
     159                 :  *
     160                 :  * @return maximum in bytes.
     161                 :  *
     162                 :  * @since GDAL 1.8.0
     163                 :  */
     164                 : 
     165          611522 : GIntBig CPL_STDCALL GDALGetCacheMax64()
     166                 : {
     167          611522 :     if( !bCacheMaxInitialized )
     168                 :     {
     169             391 :         const char* pszCacheMax = CPLGetConfigOption("GDAL_CACHEMAX",NULL);
     170             391 :         bCacheMaxInitialized = TRUE;
     171             391 :         if( pszCacheMax != NULL )
     172                 :         {
     173               2 :             GIntBig nNewCacheMax = (GIntBig)CPLScanUIntBig(pszCacheMax, strlen(pszCacheMax));
     174               2 :             if( nNewCacheMax < 100000 )
     175                 :             {
     176               2 :                 if (nNewCacheMax < 0)
     177                 :                 {
     178                 :                     CPLError(CE_Failure, CPLE_NotSupported,
     179               0 :                              "Invalid value for GDAL_CACHEMAX. Using default value.");
     180               0 :                     return nCacheMax;
     181                 :                 }
     182               2 :                 nNewCacheMax *= 1024 * 1024;
     183                 :             }
     184               2 :             nCacheMax = nNewCacheMax;
     185                 :         }
     186                 :     }
     187                 : 
     188          611522 :     return nCacheMax;
     189                 : }
     190                 : 
     191                 : /************************************************************************/
     192                 : /*                          GDALGetCacheUsed()                          */
     193                 : /************************************************************************/
     194                 : 
     195                 : /**
     196                 :  * \brief Get cache memory used.
     197                 :  *
     198                 :  * @return the number of bytes of memory currently in use by the 
     199                 :  * GDALRasterBlock memory caching.
     200                 :  */
     201                 : 
     202               0 : int CPL_STDCALL GDALGetCacheUsed()
     203                 : {
     204               0 :     if (nCacheUsed > INT_MAX)
     205                 :     {
     206                 :         static int bHasWarned = FALSE;
     207               0 :         if (!bHasWarned)
     208                 :         {
     209                 :             CPLError(CE_Warning, CPLE_AppDefined,
     210                 :                      "Cache used value doesn't fit on a 32 bit integer. "
     211               0 :                      "Call GDALGetCacheUsed64() instead");
     212               0 :             bHasWarned = TRUE;
     213                 :         }
     214               0 :         return INT_MAX;
     215                 :     }
     216               0 :     return (int)nCacheUsed;
     217                 : }
     218                 : 
     219                 : /************************************************************************/
     220                 : /*                        GDALGetCacheUsed64()                          */
     221                 : /************************************************************************/
     222                 : 
     223                 : /**
     224                 :  * \brief Get cache memory used.
     225                 :  *
     226                 :  * @return the number of bytes of memory currently in use by the
     227                 :  * GDALRasterBlock memory caching.
     228                 :  *
     229                 :  * @since GDAL 1.8.0
     230                 :  */
     231                 : 
     232               2 : GIntBig CPL_STDCALL GDALGetCacheUsed64()
     233                 : {
     234               2 :     return nCacheUsed;
     235                 : }
     236                 : 
     237                 : /************************************************************************/
     238                 : /*                        GDALFlushCacheBlock()                         */
     239                 : /*                                                                      */
     240                 : /*      The workhorse of cache management!                              */
     241                 : /************************************************************************/
     242                 : 
     243                 : /**
     244                 :  * \brief Try to flush one cached raster block
     245                 :  *
     246                 :  * This function will search the first unlocked raster block and will
     247                 :  * flush it to release the associated memory.
     248                 :  *
     249                 :  * @return TRUE if one block was flushed, FALSE if there are no cached blocks
     250                 :  *         or if they are currently locked.
     251                 :  */
     252            7975 : int CPL_STDCALL GDALFlushCacheBlock()
     253                 : 
     254                 : {
     255            7975 :     return GDALRasterBlock::FlushCacheBlock();
     256                 : }
     257                 : 
     258                 : /************************************************************************/
     259                 : /* ==================================================================== */
     260                 : /*                           GDALRasterBlock                            */
     261                 : /* ==================================================================== */
     262                 : /************************************************************************/
     263                 : 
     264                 : /**
     265                 :  * \class GDALRasterBlock "gdal_priv.h"
     266                 :  *
     267                 :  * GDALRasterBlock objects hold one block of raster data for one band
     268                 :  * that is currently stored in the GDAL raster cache.  The cache holds
     269                 :  * some blocks of raster data for zero or more GDALRasterBand objects
     270                 :  * across zero or more GDALDataset objects in a global raster cache with
     271                 :  * a least recently used (LRU) list and an upper cache limit (see
     272                 :  * GDALSetCacheMax()) under which the cache size is normally kept. 
     273                 :  *
     274                 :  * Some blocks in the cache may be modified relative to the state on disk
     275                 :  * (they are marked "Dirty") and must be flushed to disk before they can
     276                 :  * be discarded.  Other (Clean) blocks may just be discarded if their memory
     277                 :  * needs to be recovered. 
     278                 :  *
     279                 :  * In normal situations applications do not interact directly with the
     280                 :  * GDALRasterBlock - instead it it utilized by the RasterIO() interfaces
     281                 :  * to implement caching. 
     282                 :  *
     283                 :  * Some driver classes are implemented in a fashion that completely avoids
     284                 :  * use of the GDAL raster cache (and GDALRasterBlock) though this is not very
     285                 :  * common.
     286                 :  */
     287                 : 
     288                 : /************************************************************************/
     289                 : /*                          FlushCacheBlock()                           */
     290                 : /*                                                                      */
     291                 : /*      Note, if we have alot of blocks locked for a long time, this    */
     292                 : /*      method is going to get slow because it will have to traverse    */
     293                 : /*      the linked list a long ways looking for a flushing              */
     294                 : /*      candidate.   It might help to re-touch locked blocks to push    */
     295                 : /*      them to the top of the list.                                    */
     296                 : /************************************************************************/
     297                 : 
     298                 : /**
     299                 :  * \brief Attempt to flush at least one block from the cache.
     300                 :  *
     301                 :  * This static method is normally used to recover memory when a request
     302                 :  * for a new cache block would put cache memory use over the established
     303                 :  * limit.   
     304                 :  *
     305                 :  * C++ analog to the C function GDALFlushCacheBlock().
     306                 :  * 
     307                 :  * @return TRUE if successful or FALSE if no flushable block is found.
     308                 :  */
     309                 : 
     310            7975 : int GDALRasterBlock::FlushCacheBlock()
     311                 : 
     312                 : {
     313                 :     int nXOff, nYOff;
     314                 :     GDALRasterBand *poBand;
     315                 : 
     316                 :     {
     317            7975 :         CPLMutexHolderD( &hRBMutex );
     318            7975 :         GDALRasterBlock *poTarget = (GDALRasterBlock *) poOldest;
     319                 : 
     320           15950 :         while( poTarget != NULL && poTarget->GetLockCount() > 0 ) 
     321               0 :             poTarget = poTarget->poPrevious;
     322                 :         
     323            7975 :         if( poTarget == NULL )
     324             476 :             return FALSE;
     325                 : 
     326            7499 :         poTarget->Detach();
     327                 : 
     328            7499 :         nXOff = poTarget->GetXOff();
     329            7499 :         nYOff = poTarget->GetYOff();
     330            7499 :         poBand = poTarget->GetBand();
     331                 :     }
     332                 : 
     333            7499 :     CPLErr eErr = poBand->FlushBlock( nXOff, nYOff );
     334            7499 :     if (eErr != CE_None)
     335                 :     {
     336                 :         /* Save the error for later reporting */
     337               0 :         poBand->SetFlushBlockErr(eErr);
     338                 :     }
     339                 : 
     340            7499 :     return TRUE;
     341                 : }
     342                 : 
     343                 : /************************************************************************/
     344                 : /*                          GDALRasterBlock()                           */
     345                 : /************************************************************************/
     346                 : 
     347                 : /**
     348                 :  * @brief GDALRasterBlock Constructor 
     349                 :  *
     350                 :  * Normally only called from GDALRasterBand::GetLockedBlockRef().
     351                 :  *
     352                 :  * @param poBandIn the raster band used as source of raster block
     353                 :  * being constructed.
     354                 :  *
     355                 :  * @param nXOffIn the horizontal block offset, with zero indicating
     356                 :  * the left most block, 1 the next block and so forth. 
     357                 :  *
     358                 :  * @param nYOffIn the vertical block offset, with zero indicating
     359                 :  * the top most block, 1 the next block and so forth.
     360                 :  */
     361                 : 
     362          431232 : GDALRasterBlock::GDALRasterBlock( GDALRasterBand *poBandIn, 
     363          431232 :                                   int nXOffIn, int nYOffIn )
     364                 : 
     365                 : {
     366          431232 :     CPLAssert( NULL != poBandIn );
     367                 : 
     368          431232 :     poBand = poBandIn;
     369                 : 
     370          431232 :     poBand->GetBlockSize( &nXSize, &nYSize );
     371          431232 :     eType = poBand->GetRasterDataType();
     372          431232 :     pData = NULL;
     373          431232 :     bDirty = FALSE;
     374          431232 :     nLockCount = 0;
     375                 : 
     376          431232 :     poNext = poPrevious = NULL;
     377                 : 
     378          431232 :     nXOff = nXOffIn;
     379          431232 :     nYOff = nYOffIn;
     380          431232 : }
     381                 : 
     382                 : /************************************************************************/
     383                 : /*                          ~GDALRasterBlock()                          */
     384                 : /************************************************************************/
     385                 : 
     386                 : /**
     387                 :  * Block destructor. 
     388                 :  *
     389                 :  * Normally called from GDALRasterBand::FlushBlock().
     390                 :  */
     391                 : 
     392          431232 : GDALRasterBlock::~GDALRasterBlock()
     393                 : 
     394                 : {
     395          431232 :     Detach();
     396                 : 
     397          431232 :     if( pData != NULL )
     398                 :     {
     399                 :         int nSizeInBytes;
     400                 : 
     401          431232 :         VSIFree( pData );
     402                 : 
     403          431232 :         nSizeInBytes = (nXSize * nYSize * GDALGetDataTypeSize(eType)+7)/8;
     404                 : 
     405                 :         {
     406          431232 :             CPLMutexHolderD( &hRBMutex );
     407          431232 :             nCacheUsed -= nSizeInBytes;
     408                 :         }
     409                 :     }
     410                 : 
     411          431232 :     CPLAssert( nLockCount == 0 );
     412                 : 
     413                 : #ifdef ENABLE_DEBUG
     414                 :     Verify();
     415                 : #endif
     416          431232 : }
     417                 : 
     418                 : /************************************************************************/
     419                 : /*                               Detach()                               */
     420                 : /************************************************************************/
     421                 : 
     422                 : /**
     423                 :  * Remove block from cache.
     424                 :  *
     425                 :  * This method removes the current block from the linked list used to keep
     426                 :  * track of all cached blocks in order of age.  It does not affect whether
     427                 :  * the block is referenced by a GDALRasterBand nor does it destroy or flush
     428                 :  * the block.
     429                 :  */
     430                 : 
     431          869963 : void GDALRasterBlock::Detach()
     432                 : 
     433                 : {
     434          869963 :     CPLMutexHolderD( &hRBMutex );
     435                 : 
     436          869963 :     if( poOldest == this )
     437           10349 :         poOldest = poPrevious;
     438                 : 
     439          869963 :     if( poNewest == this )
     440                 :     {
     441          431700 :         poNewest = poNext;
     442                 :     }
     443                 : 
     444          869963 :     if( poPrevious != NULL )
     445            7031 :         poPrevious->poNext = poNext;
     446                 : 
     447          869963 :     if( poNext != NULL )
     448          428382 :         poNext->poPrevious = poPrevious;
     449                 : 
     450          869963 :     poPrevious = NULL;
     451          869963 :     poNext = NULL;
     452          869963 : }
     453                 : 
     454                 : /************************************************************************/
     455                 : /*                               Verify()                               */
     456                 : /************************************************************************/
     457                 : 
     458                 : /**
     459                 :  * Confirms (via assertions) that the block cache linked list is in a
     460                 :  * consistent state. 
     461                 :  */
     462                 : 
     463               0 : void GDALRasterBlock::Verify()
     464                 : 
     465                 : {
     466               0 :     CPLMutexHolderD( &hRBMutex );
     467                 : 
     468                 :     CPLAssert( (poNewest == NULL && poOldest == NULL)
     469               0 :                || (poNewest != NULL && poOldest != NULL) );
     470                 : 
     471               0 :     if( poNewest != NULL )
     472                 :     {
     473               0 :         CPLAssert( poNewest->poPrevious == NULL );
     474               0 :         CPLAssert( poOldest->poNext == NULL );
     475                 :         
     476               0 :         for( GDALRasterBlock *poBlock = (GDALRasterBlock *) poNewest; 
     477                 :              poBlock != NULL;
     478                 :              poBlock = poBlock->poNext )
     479                 :         {
     480               0 :             if( poBlock->poPrevious )
     481                 :             {
     482               0 :                 CPLAssert( poBlock->poPrevious->poNext == poBlock );
     483                 :             }
     484                 : 
     485               0 :             if( poBlock->poNext )
     486                 :             {
     487               0 :                 CPLAssert( poBlock->poNext->poPrevious == poBlock );
     488                 :             }
     489                 :         }
     490               0 :     }
     491               0 : }
     492                 : 
     493                 : /************************************************************************/
     494                 : /*                               Write()                                */
     495                 : /************************************************************************/
     496                 : 
     497                 : /**
     498                 :  * Force writing of the current block, if dirty.
     499                 :  *
     500                 :  * The block is written using GDALRasterBand::IWriteBlock() on it's 
     501                 :  * corresponding band object.  Even if the write fails the block will 
     502                 :  * be marked clean. 
     503                 :  *
     504                 :  * @return CE_None otherwise the error returned by IWriteBlock().
     505                 :  */
     506                 : 
     507           65961 : CPLErr GDALRasterBlock::Write()
     508                 : 
     509                 : {
     510           65961 :     if( !GetDirty() )
     511               0 :         return CE_None;
     512                 : 
     513           65961 :     if( poBand == NULL )
     514               0 :         return CE_Failure;
     515                 : 
     516           65961 :     MarkClean();
     517                 : 
     518           65961 :     if (poBand->eFlushBlockErr == CE_None)
     519           65961 :         return poBand->IWriteBlock( nXOff, nYOff, pData );
     520                 :     else
     521               0 :         return poBand->eFlushBlockErr;
     522                 : }
     523                 : 
     524                 : /************************************************************************/
     525                 : /*                               Touch()                                */
     526                 : /************************************************************************/
     527                 : 
     528                 : /**
     529                 :  * Push block to top of LRU (least-recently used) list.
     530                 :  *
     531                 :  * This method is normally called when a block is used to keep track 
     532                 :  * that it has been recently used. 
     533                 :  */
     534                 : 
     535         5517772 : void GDALRasterBlock::Touch()
     536                 : 
     537                 : {
     538         5517772 :     CPLMutexHolderD( &hRBMutex );
     539                 : 
     540         5517772 :     if( poNewest == this )
     541                 :         return;
     542                 : 
     543         4538907 :     if( poOldest == this )
     544         1382951 :         poOldest = this->poPrevious;
     545                 :     
     546         4538907 :     if( poPrevious != NULL )
     547         4100176 :         poPrevious->poNext = poNext;
     548                 : 
     549         4538907 :     if( poNext != NULL )
     550         2717225 :         poNext->poPrevious = poPrevious;
     551                 : 
     552         4538907 :     poPrevious = NULL;
     553         4538907 :     poNext = (GDALRasterBlock *) poNewest;
     554                 : 
     555         4538907 :     if( poNewest != NULL )
     556                 :     {
     557         4535589 :         CPLAssert( poNewest->poPrevious == NULL );
     558         4535589 :         poNewest->poPrevious = this;
     559                 :     }
     560         4538907 :     poNewest = this;
     561                 :     
     562         4538907 :     if( poOldest == NULL )
     563                 :     {
     564            3318 :         CPLAssert( poPrevious == NULL && poNext == NULL );
     565            3318 :         poOldest = this;
     566               0 :     }
     567                 : #ifdef ENABLE_DEBUG
     568                 :     Verify();
     569                 : #endif
     570                 : }
     571                 : 
     572                 : /************************************************************************/
     573                 : /*                            Internalize()                             */
     574                 : /************************************************************************/
     575                 : 
     576                 : /**
     577                 :  * Allocate memory for block.
     578                 :  *
     579                 :  * This method allocates memory for the block, and attempts to flush other
     580                 :  * blocks, if necessary, to bring the total cache size back within the limits.
     581                 :  * The newly allocated block is touched and will be considered most recently
     582                 :  * used in the LRU list. 
     583                 :  * 
     584                 :  * @return CE_None on success or CE_Failure if memory allocation fails. 
     585                 :  */
     586                 : 
     587          431232 : CPLErr GDALRasterBlock::Internalize()
     588                 : 
     589                 : {
     590          431232 :     CPLMutexHolderD( &hRBMutex );
     591                 :     void        *pNewData;
     592                 :     int         nSizeInBytes;
     593          431232 :     GIntBig     nCurCacheMax = GDALGetCacheMax64();
     594                 : 
     595                 :     /* No risk of overflow as it is checked in GDALRasterBand::InitBlockInfo() */
     596          431232 :     nSizeInBytes = nXSize * nYSize * (GDALGetDataTypeSize(eType) / 8);
     597                 : 
     598          431232 :     pNewData = VSIMalloc( nSizeInBytes );
     599          431232 :     if( pNewData == NULL )
     600                 :     {
     601                 :         CPLError( CE_Failure, CPLE_OutOfMemory, 
     602                 :                   "GDALRasterBlock::Internalize : Out of memory allocating %d bytes.",
     603               0 :                   nSizeInBytes);
     604               0 :         return( CE_Failure );
     605                 :     }
     606                 : 
     607          431232 :     if( pData != NULL )
     608               0 :         memcpy( pNewData, pData, nSizeInBytes );
     609                 :     
     610          431232 :     pData = pNewData;
     611                 : 
     612                 : /* -------------------------------------------------------------------- */
     613                 : /*      Flush old blocks if we are nearing our memory limit.            */
     614                 : /* -------------------------------------------------------------------- */
     615          431232 :     AddLock(); /* don't flush this block! */
     616                 : 
     617          431232 :     nCacheUsed += nSizeInBytes;
     618          869959 :     while( nCacheUsed > nCurCacheMax )
     619                 :     {
     620            7971 :         GIntBig nOldCacheUsed = nCacheUsed;
     621                 : 
     622            7971 :         GDALFlushCacheBlock();
     623                 : 
     624            7971 :         if( nCacheUsed == nOldCacheUsed )
     625             476 :             break;
     626                 :     }
     627                 : 
     628                 : /* -------------------------------------------------------------------- */
     629                 : /*      Add this block to the list.                                     */
     630                 : /* -------------------------------------------------------------------- */
     631          431232 :     Touch();
     632          431232 :     DropLock();
     633                 : 
     634          431232 :     return( CE_None );
     635                 : }
     636                 : 
     637                 : /************************************************************************/
     638                 : /*                             MarkDirty()                              */
     639                 : /************************************************************************/
     640                 : 
     641                 : /**
     642                 :  * Mark the block as modified.
     643                 :  *
     644                 :  * A dirty block is one that has been modified and will need to be written
     645                 :  * to disk before it can be flushed.
     646                 :  */
     647                 : 
     648         1611171 : void GDALRasterBlock::MarkDirty()
     649                 : 
     650                 : {
     651         1611171 :     bDirty = TRUE;
     652         1611171 : }
     653                 : 
     654                 : 
     655                 : /************************************************************************/
     656                 : /*                             MarkClean()                              */
     657                 : /************************************************************************/
     658                 : 
     659                 : /**
     660                 :  * Mark the block as unmodified.
     661                 :  *
     662                 :  * A dirty block is one that has been modified and will need to be written
     663                 :  * to disk before it can be flushed.
     664                 :  */
     665                 : 
     666           71046 : void GDALRasterBlock::MarkClean()
     667                 : 
     668                 : {
     669           71046 :     bDirty = FALSE;
     670           71046 : }
     671                 : 
     672                 : /************************************************************************/
     673                 : /*                           SafeLockBlock()                            */
     674                 : /************************************************************************/
     675                 : 
     676                 : /**
     677                 :  * \brief Safely lock block.
     678                 :  *
     679                 :  * This method locks a GDALRasterBlock (and touches it) in a thread-safe
     680                 :  * manner.  The global block cache mutex is held while locking the block,
     681                 :  * in order to avoid race conditions with other threads that might be
     682                 :  * trying to expire the block at the same time.  The block pointer may be
     683                 :  * safely NULL, in which case this method does nothing. 
     684                 :  *
     685                 :  * @param ppBlock Pointer to the block pointer to try and lock/touch.
     686                 :  */
     687                 :  
     688         5086904 : int GDALRasterBlock::SafeLockBlock( GDALRasterBlock ** ppBlock )
     689                 : 
     690                 : {
     691         5086904 :     CPLAssert( NULL != ppBlock );
     692                 : 
     693         5086904 :     CPLMutexHolderD( &hRBMutex );
     694                 : 
     695         5086904 :     if( *ppBlock != NULL )
     696                 :     {
     697         4655308 :         (*ppBlock)->AddLock();
     698         4655308 :         (*ppBlock)->Touch();
     699                 :         
     700         4655308 :         return TRUE;
     701                 :     }
     702                 :     else
     703          431596 :         return FALSE;
     704                 : }

Generated by: LCOV version 1.7