00001 00002 00003 00004 00005 00006 00007 00008 00009 00010 00011 00012 00013 00014 00015 00016 00017 00018 00019 00020 00021 00022 00023 00024 00025 00026 00027 00028 00028 00028 00028 00029 00030 00031 00032 00033 00034 00035 00036 00037 00038
00039
00040 #include "gdal_priv.h"
00041
00042 static int nTileAgeTicker = 0;
00043 static int nCacheMax = 5 * 1024*1024;
00044 static int nCacheUsed = 0;
00045
00046 static GDALRasterBlock *poOldest = NULL;
00047 static GDALRasterBlock *poNewest = NULL;
00048
00049
00050
00051
00052
00053
00054 void GDALSetCacheMax( int nNewSize )
00055
00056 {
00057 nCacheMax = nNewSize;
00058 if( nCacheUsed > nCacheMax )
00059 GDALFlushCacheBlock();
00060 }
00061
00062
00063
00064
00065
00066 int GDALGetCacheMax()
00067 {
00068 return nCacheMax;
00069 }
00070
00071
00072
00073
00074
00075 int GDALGetCacheUsed()
00076 {
00077 return nCacheUsed;
00078 }
00079
00080
00081
00082
00083
00084
00085
00086 int GDALFlushCacheBlock()
00087
00088 {
00089 if( poOldest == NULL )
00090 return FALSE;
00091 poOldest->GetBand()->FlushBlock( poOldest->GetXOff(),
00092 poOldest->GetYOff() );
00093
00094 return TRUE;
00095 }
00096
00097
00098
00099
00100
00101 GDALRasterBlock::GDALRasterBlock( GDALRasterBand *poBandIn,
00102 int nXOffIn, int nYOffIn )
00103
00104 {
00105 poBand = poBandIn;
00106
00107 poBand->GetBlockSize( &nXSize, &nYSize );
00108 eType = poBand->GetRasterDataType();
00109 pData = NULL;
00110 bDirty = FALSE;
00111
00112 poNext = poPrevious = NULL;
00113
00114 nXOff = nXOffIn;
00115 nYOff = nYOffIn;
00116 }
00117
00118
00119
00120
00121
00122 GDALRasterBlock::~GDALRasterBlock()
00123
00124 {
00125 if( pData != NULL )
00126 {
00127 int nSizeInBytes;
00128
00129 VSIFree( pData );
00130
00131 nSizeInBytes = (nXSize * nYSize * GDALGetDataTypeSize(eType)+7)/8;
00132 nCacheUsed -= nSizeInBytes;
00133 }
00134
00135 if( poOldest == this )
00136 poOldest = poPrevious;
00137
00138 if( poNewest == this )
00139 {
00140 poNewest = poNext;
00141 }
00142
00143 if( poPrevious != NULL )
00144 poPrevious->poNext = poNext;
00145
00146 if( poNext != NULL )
00147 poNext->poPrevious = poPrevious;
00148
00149 #ifdef ENABLE_DEBUG
00150 Verify();
00151 #endif
00152
00153 nAge = -1;
00154 }
00155
00156
00157
00158
00159
00160 void GDALRasterBlock::Verify()
00161
00162 {
00163 CPLAssert( (poNewest == NULL && poOldest == NULL)
00164 || (poNewest != NULL && poOldest != NULL) );
00165
00166 if( poNewest != NULL )
00167 {
00168 CPLAssert( poNewest->poPrevious == NULL );
00169 CPLAssert( poOldest->poNext == NULL );
00170
00171
00172 for( GDALRasterBlock *poBlock = poNewest;
00173 poBlock != NULL;
00174 poBlock = poBlock->poNext )
00175 {
00176 if( poBlock->poPrevious )
00177 {
00178 CPLAssert( poBlock->poPrevious->poNext == poBlock );
00179 }
00180
00181 if( poBlock->poNext )
00182 {
00183 CPLAssert( poBlock->poNext->poPrevious == poBlock );
00184 }
00185 }
00186 }
00187 }
00188
00189
00190
00191
00192
00193 CPLErr GDALRasterBlock::Write()
00194
00195 {
00196 if( !GetDirty() )
00197 return CE_None;
00198
00199 if( poBand == NULL )
00200 return CE_Failure;
00201
00202 MarkClean();
00203
00204 return poBand->IWriteBlock( nXOff, nYOff, pData );
00205 }
00206
00207
00208
00209
00210
00211 void GDALRasterBlock::Touch()
00212
00213 {
00214 nAge = nTileAgeTicker++;
00215
00216 if( poNewest == this )
00217 return;
00218
00219 if( poOldest == this )
00220 poOldest = this->poPrevious;
00221
00222 if( poPrevious != NULL )
00223 poPrevious->poNext = poNext;
00224
00225 if( poNext != NULL )
00226 poNext->poPrevious = poPrevious;
00227
00228 poPrevious = NULL;
00229 poNext = poNewest;
00230
00231 if( poNewest != NULL )
00232 {
00233 CPLAssert( poNewest->poPrevious == NULL );
00234 poNewest->poPrevious = this;
00235 }
00236 poNewest = this;
00237
00238 if( poOldest == NULL )
00239 {
00240 CPLAssert( poPrevious == NULL && poNext == NULL );
00241 poOldest = this;
00242 }
00243 #ifdef ENABLE_DEBUG
00244 Verify();
00245 #endif
00246 }
00247
00248
00249
00250
00251
00252 CPLErr GDALRasterBlock::Internalize()
00253
00254 {
00255 void *pNewData;
00256 int nSizeInBytes;
00257
00258 nSizeInBytes = (nXSize * nYSize * GDALGetDataTypeSize( eType ) + 7) / 8;
00259
00260 pNewData = VSIMalloc( nSizeInBytes );
00261 if( pNewData == NULL )
00262 return( CE_Failure );
00263
00264 if( pData != NULL )
00265 memcpy( pNewData, pData, nSizeInBytes );
00266
00267 pData = pNewData;
00268
00269
00270
00271
00272 nCacheUsed += nSizeInBytes;
00273 while( nCacheUsed > nCacheMax )
00274 {
00275 int nOldCacheUsed = nCacheUsed;
00276
00277 GDALFlushCacheBlock();
00278
00279 if( nCacheUsed == nOldCacheUsed )
00280 {
00281 static int bReported = FALSE;
00282
00283 if( !bReported )
00284 {
00285 bReported = TRUE;
00286 }
00287 break;
00288 }
00289 }
00290
00291
00292
00293
00294 Touch();
00295 return( CE_None );
00296 }
00297
00298
00299
00300
00301
00302 void GDALRasterBlock::MarkDirty()
00303
00304 {
00305 bDirty = TRUE;
00306 }
00307
00308
00309
00310
00311
00312
00313 void GDALRasterBlock::MarkClean()
00314
00315 {
00316 bDirty = FALSE;
00317 }
00318
00319