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.1  2000/09/25 20:50:11  warmerda
00028  * New
00028  *
00029  * Revision 1.3  2000/03/31 13:42:49  warmerda
00030  * added debugging code
00031  *
00032  * Revision 1.2  2000/03/24 00:09:05  warmerda
00033  * rewrote cache management
00034  *
00035  * Revision 1.1  1998/12/31 18:52:58  warmerda
00036  * New
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;    /* tail */
00047 static GDALRasterBlock   *poNewest = NULL;    /* head */
00048 
00049 
00050 /************************************************************************/
00051 /*                          GDALSetCacheMax()                           */
00052 /************************************************************************/
00053 
00054 void GDALSetCacheMax( int nNewSize )
00055 
00056 {
00057     nCacheMax = nNewSize;
00058     if( nCacheUsed > nCacheMax )
00059         GDALFlushCacheBlock();
00060 }
00061 
00062 /************************************************************************/
00063 /*                          GDALGetCacheMax()                           */
00064 /************************************************************************/
00065 
00066 int GDALGetCacheMax()
00067 {
00068     return nCacheMax;
00069 }
00070 
00071 /************************************************************************/
00072 /*                          GDALGetCacheUsed()                          */
00073 /************************************************************************/
00074 
00075 int GDALGetCacheUsed()
00076 {
00077     return nCacheUsed;
00078 }
00079 
00080 /************************************************************************/
00081 /*                        GDALFlushCacheBlock()                         */
00082 /*                                                                      */
00083 /*      The workhorse of cache management!                              */
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 /*                           GDALRasterBand()                           */
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 /*                          ~GDALRasterBlock()                          */
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 /*                               Verify()                               */
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 /*                               Write()                                */
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 /*                               Touch()                                */
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 /*                            Internalize()                             */
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 /*      Flush old blocks if we are nearing our memory limit.            */
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 /*      Add this block to the list.                                     */
00293 /* -------------------------------------------------------------------- */
00294     Touch();
00295     return( CE_None );
00296 }
00297 
00298 /************************************************************************/
00299 /*                             MarkDirty()                              */
00300 /************************************************************************/
00301 
00302 void GDALRasterBlock::MarkDirty()
00303 
00304 {
00305     bDirty = TRUE;
00306 }
00307 
00308 
00309 /************************************************************************/
00310 /*                             MarkClean()                              */
00311 /************************************************************************/
00312 
00313 void GDALRasterBlock::MarkClean()
00314 
00315 {
00316     bDirty = FALSE;
00317 }
00318 
00319 

doxygen1.2.2 Dimitri van Heesch, © 1997-2000