Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members   Related Pages  

gdalrasterblock.cpp

00001 /******************************************************************************
00002  * Copyright (c) 1998, Frank Warmerdam
00003  *
00004  * Permission is hereby granted, free of charge, to any person obtaining a
00005  * copy of this software and associated documentation files (the "Software"),
00006  * to deal in the Software without restriction, including without limitation
00007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00008  * and/or sell copies of the Software, and to permit persons to whom the
00009  * Software is furnished to do so, subject to the following conditions:
00010  *
00011  * The above copyright notice and this permission notice shall be included
00012  * in all copies or substantial portions of the Software.
00013  *
00014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00015  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
00017  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00018  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00019  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
00020  * DEALINGS IN THE SOFTWARE.
00021  ******************************************************************************
00022  *
00023  * gdalrasterblock.cpp
00024  *
00025  * The GDALRasterBlock class.
00026  *
00027  * 
00028  * $Log: gdalrasterblock_cpp-source.html,v $
00028  * Revision 1.8  2001/07/05 13:24:08  warmerda
00028  * *** empty log message ***
00028  *
00029  * Revision 1.5  2001/06/22 21:00:06  warmerda
00030  * fixed support for caching override by environment variable
00031  *
00032  * Revision 1.4  2001/06/22 20:09:13  warmerda
00033  * added GDAL_CACHEMAX environment variable support
00034  *
00035  * Revision 1.3  2000/03/31 13:42:49  warmerda
00036  * added debugging code
00037  *
00038  * Revision 1.2  2000/03/24 00:09:05  warmerda
00039  * rewrote cache management
00040  *
00041  * Revision 1.1  1998/12/31 18:52:58  warmerda
00042  * New
00043  *
00044  */
00045 
00046 #include "gdal_priv.h"
00047 
00048 static int nTileAgeTicker = 0; 
00049 static int bCacheMaxInitialized = FALSE;
00050 static int nCacheMax = 5 * 1024*1024;
00051 static int nCacheUsed = 0;
00052 
00053 static GDALRasterBlock   *poOldest = NULL;    /* tail */
00054 static GDALRasterBlock   *poNewest = NULL;    /* head */
00055 
00056 
00057 /************************************************************************/
00058 /*                          GDALSetCacheMax()                           */
00059 /************************************************************************/
00060 
00061 void GDALSetCacheMax( int nNewSize )
00062 
00063 {
00064     nCacheMax = nNewSize;
00065     if( nCacheUsed > nCacheMax )
00066         GDALFlushCacheBlock();
00067 }
00068 
00069 /************************************************************************/
00070 /*                          GDALGetCacheMax()                           */
00071 /************************************************************************/
00072 
00073 int GDALGetCacheMax()
00074 {
00075     if( !bCacheMaxInitialized )
00076     {
00077         if( getenv("GDAL_CACHEMAX") != NULL )
00078         {
00079             nCacheMax = atoi(getenv("GDAL_CACHEMAX"));
00080             if( nCacheMax < 1000 )
00081                 nCacheMax *= 1024 * 1024;
00082         }
00083         bCacheMaxInitialized = TRUE;
00084     }
00085     
00086     return nCacheMax;
00087 }
00088 
00089 /************************************************************************/
00090 /*                          GDALGetCacheUsed()                          */
00091 /************************************************************************/
00092 
00093 int GDALGetCacheUsed()
00094 {
00095     return nCacheUsed;
00096 }
00097 
00098 /************************************************************************/
00099 /*                        GDALFlushCacheBlock()                         */
00100 /*                                                                      */
00101 /*      The workhorse of cache management!                              */
00102 /************************************************************************/
00103 
00104 int GDALFlushCacheBlock()
00105 
00106 {
00107     if( poOldest == NULL )
00108         return FALSE;
00109     poOldest->GetBand()->FlushBlock( poOldest->GetXOff(), 
00110                                      poOldest->GetYOff() );
00111 
00112     return TRUE;
00113 }
00114 
00115 /************************************************************************/
00116 /*                           GDALRasterBand()                           */
00117 /************************************************************************/
00118 
00119 GDALRasterBlock::GDALRasterBlock( GDALRasterBand *poBandIn, 
00120                                   int nXOffIn, int nYOffIn )
00121 
00122 {
00123     poBand = poBandIn;
00124 
00125     poBand->GetBlockSize( &nXSize, &nYSize );
00126     eType = poBand->GetRasterDataType();
00127     pData = NULL;
00128     bDirty = FALSE;
00129 
00130     poNext = poPrevious = NULL;
00131 
00132     nXOff = nXOffIn;
00133     nYOff = nYOffIn;
00134 }
00135 
00136 /************************************************************************/
00137 /*                          ~GDALRasterBlock()                          */
00138 /************************************************************************/
00139 
00140 GDALRasterBlock::~GDALRasterBlock()
00141 
00142 {
00143     if( pData != NULL )
00144     {
00145         int nSizeInBytes;
00146 
00147         VSIFree( pData );
00148 
00149         nSizeInBytes = (nXSize * nYSize * GDALGetDataTypeSize(eType)+7)/8;
00150         nCacheUsed -= nSizeInBytes;
00151     }
00152 
00153     if( poOldest == this )
00154         poOldest = poPrevious;
00155 
00156     if( poNewest == this )
00157     {
00158         poNewest = poNext;
00159     }
00160 
00161     if( poPrevious != NULL )
00162         poPrevious->poNext = poNext;
00163 
00164     if( poNext != NULL )
00165         poNext->poPrevious = poPrevious;
00166 
00167 #ifdef ENABLE_DEBUG
00168     Verify();
00169 #endif
00170 
00171     nAge = -1;
00172 }
00173 
00174 /************************************************************************/
00175 /*                               Verify()                               */
00176 /************************************************************************/
00177 
00178 void GDALRasterBlock::Verify()
00179 
00180 {
00181     CPLAssert( (poNewest == NULL && poOldest == NULL)
00182                || (poNewest != NULL && poOldest != NULL) );
00183 
00184     if( poNewest != NULL )
00185     {
00186         CPLAssert( poNewest->poPrevious == NULL );
00187         CPLAssert( poOldest->poNext == NULL );
00188         
00189 
00190         for( GDALRasterBlock *poBlock = poNewest; 
00191              poBlock != NULL;
00192              poBlock = poBlock->poNext )
00193         {
00194             if( poBlock->poPrevious )
00195             {
00196                 CPLAssert( poBlock->poPrevious->poNext == poBlock );
00197             }
00198 
00199             if( poBlock->poNext )
00200             {
00201                 CPLAssert( poBlock->poNext->poPrevious == poBlock );
00202             }
00203         }
00204     }
00205 }
00206 
00207 /************************************************************************/
00208 /*                               Write()                                */
00209 /************************************************************************/
00210 
00211 CPLErr GDALRasterBlock::Write()
00212 
00213 {
00214     if( !GetDirty() )
00215         return CE_None;
00216 
00217     if( poBand == NULL )
00218         return CE_Failure;
00219 
00220     MarkClean();
00221 
00222     return poBand->IWriteBlock( nXOff, nYOff, pData );
00223 }
00224 
00225 /************************************************************************/
00226 /*                               Touch()                                */
00227 /************************************************************************/
00228 
00229 void GDALRasterBlock::Touch()
00230 
00231 {
00232     nAge = nTileAgeTicker++;
00233 
00234     if( poNewest == this )
00235         return;
00236 
00237     if( poOldest == this )
00238         poOldest = this->poPrevious;
00239     
00240     if( poPrevious != NULL )
00241         poPrevious->poNext = poNext;
00242 
00243     if( poNext != NULL )
00244         poNext->poPrevious = poPrevious;
00245 
00246     poPrevious = NULL;
00247     poNext = poNewest;
00248 
00249     if( poNewest != NULL )
00250     {
00251         CPLAssert( poNewest->poPrevious == NULL );
00252         poNewest->poPrevious = this;
00253     }
00254     poNewest = this;
00255     
00256     if( poOldest == NULL )
00257     {
00258         CPLAssert( poPrevious == NULL && poNext == NULL );
00259         poOldest = this;
00260     }
00261 #ifdef ENABLE_DEBUG
00262     Verify();
00263 #endif
00264 }
00265 
00266 /************************************************************************/
00267 /*                            Internalize()                             */
00268 /************************************************************************/
00269 
00270 CPLErr GDALRasterBlock::Internalize()
00271 
00272 {
00273     void        *pNewData;
00274     int         nSizeInBytes;
00275     int         nCurCacheMax = GDALGetCacheMax();
00276 
00277     nSizeInBytes = (nXSize * nYSize * GDALGetDataTypeSize( eType ) + 7) / 8;
00278 
00279     pNewData = VSIMalloc( nSizeInBytes );
00280     if( pNewData == NULL )
00281         return( CE_Failure );
00282 
00283     if( pData != NULL )
00284         memcpy( pNewData, pData, nSizeInBytes );
00285     
00286     pData = pNewData;
00287 
00288 /* -------------------------------------------------------------------- */
00289 /*      Flush old blocks if we are nearing our memory limit.            */
00290 /* -------------------------------------------------------------------- */
00291     nCacheUsed += nSizeInBytes;
00292     while( nCacheUsed > nCurCacheMax )
00293     {
00294         int nOldCacheUsed = nCacheUsed;
00295 
00296         GDALFlushCacheBlock();
00297 
00298         if( nCacheUsed == nOldCacheUsed )
00299         {
00300             static int bReported = FALSE;
00301 
00302             if( !bReported )
00303             {
00304                 bReported = TRUE;
00305             }
00306             break;
00307         }
00308     }
00309 
00310 /* -------------------------------------------------------------------- */
00311 /*      Add this block to the list.                                     */
00312 /* -------------------------------------------------------------------- */
00313     Touch();
00314     return( CE_None );
00315 }
00316 
00317 /************************************************************************/
00318 /*                             MarkDirty()                              */
00319 /************************************************************************/
00320 
00321 void GDALRasterBlock::MarkDirty()
00322 
00323 {
00324     bDirty = TRUE;
00325 }
00326 
00327 
00328 /************************************************************************/
00329 /*                             MarkClean()                              */
00330 /************************************************************************/
00331 
00332 void GDALRasterBlock::MarkClean()
00333 
00334 {
00335     bDirty = FALSE;
00336 }
00337 
00338 

Generated at Thu Jul 5 09:16:13 2001 for GDAL by doxygen1.2.3-20001105 written by Dimitri van Heesch, © 1997-2000