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.13 2002/12/21 19:13:13 warmerda
00028 * updated
00028 *
00029 * Revision 1.8 2002/07/09 20:33:12 warmerda
00030 * expand tabs
00031 *
00032 * Revision 1.7 2001/09/27 16:33:41 warmerda
00033 * fixed problems with blocks larger than 2GB/8
00034 *
00035 * Revision 1.6 2001/07/18 04:04:30 warmerda
00036 * added CPL_CVSID
00037 *
00038 * Revision 1.5 2001/06/22 21:00:06 warmerda
00039 * fixed support for caching override by environment variable
00040 *
00041 * Revision 1.4 2001/06/22 20:09:13 warmerda
00042 * added GDAL_CACHEMAX environment variable support
00043 *
00044 * Revision 1.3 2000/03/31 13:42:49 warmerda
00045 * added debugging code
00046 *
00047 * Revision 1.2 2000/03/24 00:09:05 warmerda
00048 * rewrote cache management
00049 *
00050 * Revision 1.1 1998/12/31 18:52:58 warmerda
00051 * New
00052 *
00053 */
00054
00055 #include "gdal_priv.h"
00056
00057 CPL_CVSID("$Id: gdalrasterblock_cpp-source.html,v 1.13 2002/12/21 19:13:13 warmerda Exp $");
00058
00059 static int nTileAgeTicker = 0;
00060 static int bCacheMaxInitialized = FALSE;
00061 static int nCacheMax = 5 * 1024*1024;
00062 static int nCacheUsed = 0;
00063
00064 static GDALRasterBlock *poOldest = NULL; /* tail */
00065 static GDALRasterBlock *poNewest = NULL; /* head */
00066
00067
00068 /************************************************************************/
00069 /* GDALSetCacheMax() */
00070 /************************************************************************/
00071
00072 void GDALSetCacheMax( int nNewSize )
00073
00074 {
00075 nCacheMax = nNewSize;
00076 if( nCacheUsed > nCacheMax )
00077 GDALFlushCacheBlock();
00078 }
00079
00080 /************************************************************************/
00081 /* GDALGetCacheMax() */
00082 /************************************************************************/
00083
00084 int GDALGetCacheMax()
00085 {
00086 if( !bCacheMaxInitialized )
00087 {
00088 if( getenv("GDAL_CACHEMAX") != NULL )
00089 {
00090 nCacheMax = atoi(getenv("GDAL_CACHEMAX"));
00091 if( nCacheMax < 1000 )
00092 nCacheMax *= 1024 * 1024;
00093 }
00094 bCacheMaxInitialized = TRUE;
00095 }
00096
00097 return nCacheMax;
00098 }
00099
00100 /************************************************************************/
00101 /* GDALGetCacheUsed() */
00102 /************************************************************************/
00103
00104 int GDALGetCacheUsed()
00105 {
00106 return nCacheUsed;
00107 }
00108
00109 /************************************************************************/
00110 /* GDALFlushCacheBlock() */
00111 /* */
00112 /* The workhorse of cache management! */
00113 /************************************************************************/
00114
00115 int GDALFlushCacheBlock()
00116
00117 {
00118 if( poOldest == NULL )
00119 return FALSE;
00120 poOldest->GetBand()->FlushBlock( poOldest->GetXOff(),
00121 poOldest->GetYOff() );
00122
00123 return TRUE;
00124 }
00125
00126 /************************************************************************/
00127 /* GDALRasterBand() */
00128 /************************************************************************/
00129
00130 GDALRasterBlock::GDALRasterBlock( GDALRasterBand *poBandIn,
00131 int nXOffIn, int nYOffIn )
00132
00133 {
00134 poBand = poBandIn;
00135
00136 poBand->GetBlockSize( &nXSize, &nYSize );
00137 eType = poBand->GetRasterDataType();
00138 pData = NULL;
00139 bDirty = FALSE;
00140
00141 poNext = poPrevious = NULL;
00142
00143 nXOff = nXOffIn;
00144 nYOff = nYOffIn;
00145 }
00146
00147 /************************************************************************/
00148 /* ~GDALRasterBlock() */
00149 /************************************************************************/
00150
00151 GDALRasterBlock::~GDALRasterBlock()
00152
00153 {
00154 if( pData != NULL )
00155 {
00156 int nSizeInBytes;
00157
00158 VSIFree( pData );
00159
00160 nSizeInBytes = (nXSize * nYSize * GDALGetDataTypeSize(eType)+7)/8;
00161 nCacheUsed -= nSizeInBytes;
00162 }
00163
00164 if( poOldest == this )
00165 poOldest = poPrevious;
00166
00167 if( poNewest == this )
00168 {
00169 poNewest = poNext;
00170 }
00171
00172 if( poPrevious != NULL )
00173 poPrevious->poNext = poNext;
00174
00175 if( poNext != NULL )
00176 poNext->poPrevious = poPrevious;
00177
00178 #ifdef ENABLE_DEBUG
00179 Verify();
00180 #endif
00181
00182 nAge = -1;
00183 }
00184
00185 /************************************************************************/
00186 /* Verify() */
00187 /************************************************************************/
00188
00189 void GDALRasterBlock::Verify()
00190
00191 {
00192 CPLAssert( (poNewest == NULL && poOldest == NULL)
00193 || (poNewest != NULL && poOldest != NULL) );
00194
00195 if( poNewest != NULL )
00196 {
00197 CPLAssert( poNewest->poPrevious == NULL );
00198 CPLAssert( poOldest->poNext == NULL );
00199
00200
00201 for( GDALRasterBlock *poBlock = poNewest;
00202 poBlock != NULL;
00203 poBlock = poBlock->poNext )
00204 {
00205 if( poBlock->poPrevious )
00206 {
00207 CPLAssert( poBlock->poPrevious->poNext == poBlock );
00208 }
00209
00210 if( poBlock->poNext )
00211 {
00212 CPLAssert( poBlock->poNext->poPrevious == poBlock );
00213 }
00214 }
00215 }
00216 }
00217
00218 /************************************************************************/
00219 /* Write() */
00220 /************************************************************************/
00221
00222 CPLErr GDALRasterBlock::Write()
00223
00224 {
00225 if( !GetDirty() )
00226 return CE_None;
00227
00228 if( poBand == NULL )
00229 return CE_Failure;
00230
00231 MarkClean();
00232
00233 return poBand->IWriteBlock( nXOff, nYOff, pData );
00234 }
00235
00236 /************************************************************************/
00237 /* Touch() */
00238 /************************************************************************/
00239
00240 void GDALRasterBlock::Touch()
00241
00242 {
00243 nAge = nTileAgeTicker++;
00244
00245 if( poNewest == this )
00246 return;
00247
00248 if( poOldest == this )
00249 poOldest = this->poPrevious;
00250
00251 if( poPrevious != NULL )
00252 poPrevious->poNext = poNext;
00253
00254 if( poNext != NULL )
00255 poNext->poPrevious = poPrevious;
00256
00257 poPrevious = NULL;
00258 poNext = poNewest;
00259
00260 if( poNewest != NULL )
00261 {
00262 CPLAssert( poNewest->poPrevious == NULL );
00263 poNewest->poPrevious = this;
00264 }
00265 poNewest = this;
00266
00267 if( poOldest == NULL )
00268 {
00269 CPLAssert( poPrevious == NULL && poNext == NULL );
00270 poOldest = this;
00271 }
00272 #ifdef ENABLE_DEBUG
00273 Verify();
00274 #endif
00275 }
00276
00277 /************************************************************************/
00278 /* Internalize() */
00279 /************************************************************************/
00280
00281 CPLErr GDALRasterBlock::Internalize()
00282
00283 {
00284 void *pNewData;
00285 int nSizeInBytes;
00286 int nCurCacheMax = GDALGetCacheMax();
00287
00288 nSizeInBytes = nXSize * nYSize * (GDALGetDataTypeSize(eType) / 8);
00289
00290 pNewData = VSIMalloc( nSizeInBytes );
00291 if( pNewData == NULL )
00292 return( CE_Failure );
00293
00294 if( pData != NULL )
00295 memcpy( pNewData, pData, nSizeInBytes );
00296
00297 pData = pNewData;
00298
00299 /* -------------------------------------------------------------------- */
00300 /* Flush old blocks if we are nearing our memory limit. */
00301 /* -------------------------------------------------------------------- */
00302 nCacheUsed += nSizeInBytes;
00303 while( nCacheUsed > nCurCacheMax )
00304 {
00305 int nOldCacheUsed = nCacheUsed;
00306
00307 GDALFlushCacheBlock();
00308
00309 if( nCacheUsed == nOldCacheUsed )
00310 {
00311 static int bReported = FALSE;
00312
00313 if( !bReported )
00314 {
00315 bReported = TRUE;
00316 }
00317 break;
00318 }
00319 }
00320
00321 /* -------------------------------------------------------------------- */
00322 /* Add this block to the list. */
00323 /* -------------------------------------------------------------------- */
00324 Touch();
00325 return( CE_None );
00326 }
00327
00328 /************************************************************************/
00329 /* MarkDirty() */
00330 /************************************************************************/
00331
00332 void GDALRasterBlock::MarkDirty()
00333
00334 {
00335 bDirty = TRUE;
00336 }
00337
00338
00339 /************************************************************************/
00340 /* MarkClean() */
00341 /************************************************************************/
00342
00343 void GDALRasterBlock::MarkClean()
00344
00345 {
00346 bDirty = FALSE;
00347 }
00348
00349
1.2.3-20001105 written by Dimitri van Heesch,
© 1997-2000