LCOV - code coverage report
Current view: directory - gcore - gdalproxypool.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 473 200 42.3 %
Date: 2010-01-09 Functions: 58 23 39.7 %

       1                 : /******************************************************************************
       2                 :  * $Id: gdalproxypool.cpp 17636 2009-09-12 23:19:18Z warmerdam $
       3                 :  *
       4                 :  * Project:  GDAL Core
       5                 :  * Purpose:  A dataset and raster band classes that differ the opening of the
       6                 :  *           underlying dataset in a limited pool of opened datasets.
       7                 :  * Author:   Even Rouault <even dot rouault at mines dash paris dot org>
       8                 :  *
       9                 :  ******************************************************************************
      10                 :  * Copyright (c) 2008, Even Rouault
      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_proxy.h"
      32                 : #include "cpl_multiproc.h"
      33                 : 
      34                 : CPL_CVSID("$Id: gdalproxypool.cpp 17636 2009-09-12 23:19:18Z warmerdam $");
      35                 : 
      36                 : /* Functions shared between gdalproxypool.cpp and gdaldataset.cpp */
      37                 : void** GDALGetphDLMutex();
      38                 : void GDALSetResponsiblePIDForCurrentThread(GIntBig responsiblePID);
      39                 : GIntBig GDALGetResponsiblePIDForCurrentThread();
      40                 : 
      41                 : /* We *must* share the same mutex as the gdaldataset.cpp file, as we are */
      42                 : /* doing GDALOpen() calls that can indirectly call GDALOpenShared() on */
      43                 : /* an auxiliary dataset ... */
      44                 : /* Then we could get dead-locks in multi-threaded use case */
      45                 : 
      46                 : /* ******************************************************************** */
      47                 : /*                         GDALDatasetPool                              */
      48                 : /* ******************************************************************** */
      49                 : 
      50                 : /* This class is a singleton that maintains a pool of opened datasets */
      51                 : /* The cache uses a LRU strategy */
      52                 : 
      53                 : class GDALDatasetPool;
      54                 : static GDALDatasetPool* singleton = NULL;
      55                 : 
      56                 : struct _GDALProxyPoolCacheEntry
      57                 : {
      58                 :     GIntBig       responsiblePID;
      59                 :     char         *pszFileName;
      60                 :     GDALDataset  *poDS;
      61                 : 
      62                 :     /* Ref count of the cached dataset */
      63                 :     int           refCount;
      64                 : 
      65                 :     GDALProxyPoolCacheEntry* prev;
      66                 :     GDALProxyPoolCacheEntry* next;
      67                 : };
      68                 : 
      69                 : class GDALDatasetPool
      70                 : {
      71                 :     private:
      72                 :         /* Ref count of the pool singleton */
      73                 :         /* Taken by "toplevel" GDALProxyPoolDataset in its constructor and released */
      74                 :         /* in its destructor. See also refCountOfDisableRefCount for the difference */
      75                 :         /* between toplevel and inner GDALProxyPoolDataset */
      76                 :         int refCount;
      77                 : 
      78                 :         int maxSize;
      79                 :         int currentSize;
      80                 :         GDALProxyPoolCacheEntry* firstEntry;
      81                 :         GDALProxyPoolCacheEntry* lastEntry;
      82                 : 
      83                 :         /* This variable prevents a dataset that is going to be opened in GDALDatasetPool::_RefDataset */
      84                 :         /* from increasing refCount if, during its opening, it creates a GDALProxyPoolDataset */
      85                 :         /* We increment it before opening or closing a cached dataset and decrement it afterwards */
      86                 :         /* The typical use case is a VRT made of simple sources that are VRT */
      87                 :         /* We don't want the "inner" VRT to take a reference on the pool, otherwise there is */
      88                 :         /* a high chance that this reference will not be dropped and the pool remain ghost */
      89                 :         int refCountOfDisableRefCount;
      90                 : 
      91                 :         /* Caution : to be sure that we don't run out of entries, size must be at */
      92                 :         /* least greater or equal than the maximum number of threads */
      93                 :         GDALDatasetPool(int maxSize);
      94                 :         ~GDALDatasetPool();
      95                 :         GDALProxyPoolCacheEntry* _RefDataset(const char* pszFileName, GDALAccess eAccess);
      96                 : 
      97                 :         void ShowContent();
      98                 :         void CheckLinks();
      99                 : 
     100                 :     public:
     101                 :         static void Ref();
     102                 :         static void Unref();
     103                 :         static GDALProxyPoolCacheEntry* RefDataset(const char* pszFileName, GDALAccess eAccess);
     104                 :         static void UnrefDataset(GDALProxyPoolCacheEntry* cacheEntry);
     105                 : };
     106                 : 
     107                 : 
     108                 : /************************************************************************/
     109                 : /*                         GDALDatasetPool()                            */
     110                 : /************************************************************************/
     111                 : 
     112              44 : GDALDatasetPool::GDALDatasetPool(int maxSize)
     113                 : {
     114              44 :     this->maxSize = maxSize;
     115              44 :     currentSize = 0;
     116              44 :     firstEntry = NULL;
     117              44 :     lastEntry = NULL;
     118              44 :     refCount = 0;
     119              44 :     refCountOfDisableRefCount = 0;
     120              44 : }
     121                 : 
     122                 : /************************************************************************/
     123                 : /*                        ~GDALDatasetPool()                            */
     124                 : /************************************************************************/
     125                 : 
     126              44 : GDALDatasetPool::~GDALDatasetPool()
     127                 : {
     128              44 :     GDALProxyPoolCacheEntry* cur = firstEntry;
     129              44 :     GIntBig responsiblePID = GDALGetResponsiblePIDForCurrentThread();
     130             139 :     while(cur)
     131                 :     {
     132              51 :         GDALProxyPoolCacheEntry* next = cur->next;
     133              51 :         CPLFree(cur->pszFileName);
     134                 :         CPLAssert(cur->refCount == 0);
     135              51 :         if (cur->poDS)
     136                 :         {
     137              50 :             GDALSetResponsiblePIDForCurrentThread(cur->responsiblePID);
     138              50 :             GDALClose(cur->poDS);
     139                 :         }
     140              51 :         CPLFree(cur);
     141              51 :         cur = next;
     142                 :     }
     143              44 :     GDALSetResponsiblePIDForCurrentThread(responsiblePID);
     144              44 : }
     145                 : 
     146                 : /************************************************************************/
     147                 : /*                            ShowContent()                             */
     148                 : /************************************************************************/
     149                 : 
     150               0 : void GDALDatasetPool::ShowContent()
     151                 : {
     152               0 :     GDALProxyPoolCacheEntry* cur = firstEntry;
     153               0 :     int i = 0;
     154               0 :     while(cur)
     155                 :     {
     156                 :         printf("[%d] pszFileName=%s, refCount=%d, responsiblePID=%d\n",
     157               0 :                i, cur->pszFileName, cur->refCount, (int)cur->responsiblePID);
     158               0 :         i++;
     159               0 :         cur = cur->next;
     160                 :     }
     161               0 : }
     162                 : 
     163                 : /************************************************************************/
     164                 : /*                             CheckLinks()                             */
     165                 : /************************************************************************/
     166                 : 
     167               0 : void GDALDatasetPool::CheckLinks()
     168                 : {
     169               0 :     GDALProxyPoolCacheEntry* cur = firstEntry;
     170               0 :     int i = 0;
     171               0 :     while(cur)
     172                 :     {
     173                 :         CPLAssert(cur == firstEntry || cur->prev->next == cur);
     174                 :         CPLAssert(cur == lastEntry || cur->next->prev == cur);
     175               0 :         i++;
     176                 :   CPLAssert(cur->next != NULL || cur == lastEntry);
     177               0 :         cur = cur->next;
     178                 :     }
     179                 :     CPLAssert(i == currentSize);
     180               0 : }
     181                 : 
     182                 : /************************************************************************/
     183                 : /*                            _RefDataset()                             */
     184                 : /************************************************************************/
     185                 : 
     186            4145 : GDALProxyPoolCacheEntry* GDALDatasetPool::_RefDataset(const char* pszFileName, GDALAccess eAccess)
     187                 : {
     188            4145 :     GDALProxyPoolCacheEntry* cur = firstEntry;
     189            4145 :     GIntBig responsiblePID = GDALGetResponsiblePIDForCurrentThread();
     190            4145 :     GDALProxyPoolCacheEntry* lastEntryWithZeroRefCount = NULL;
     191                 : 
     192            8824 :     while(cur)
     193                 :     {
     194            4628 :         GDALProxyPoolCacheEntry* next = cur->next;
     195                 : 
     196            4628 :         if (strcmp(cur->pszFileName, pszFileName) == 0 &&
     197                 :             cur->responsiblePID == responsiblePID)
     198                 :         {
     199            4094 :             if (cur != firstEntry)
     200                 :             {
     201                 :                 /* Move to begin */
     202             371 :                 if (cur->next)
     203             144 :                     cur->next->prev = cur->prev;
     204                 :                 else
     205             227 :                     lastEntry = cur->prev;
     206             371 :                 cur->prev->next = cur->next;
     207             371 :                 cur->prev = NULL;
     208             371 :                 firstEntry->prev = cur;
     209             371 :                 cur->next = firstEntry;
     210             371 :                 firstEntry = cur;
     211                 : 
     212                 : #ifdef DEBUG_PROXY_POOL
     213                 :                 CheckLinks();
     214                 : #endif
     215                 :             }
     216                 : 
     217            4094 :             cur->refCount ++;
     218            4094 :             return cur;
     219                 :         }
     220                 : 
     221             534 :         if (cur->refCount == 0)
     222             451 :             lastEntryWithZeroRefCount = cur;
     223                 : 
     224             534 :         cur = next;
     225                 :     }
     226                 : 
     227              51 :     if (currentSize == maxSize)
     228                 :     {
     229               0 :         if (lastEntryWithZeroRefCount == NULL)
     230                 :         {
     231                 :             CPLError(CE_Failure, CPLE_AppDefined,
     232                 :                      "Too many threads are running for the current value of the dataset pool size (%d).\n"
     233                 :                      "or too many proxy datasets are opened in a cascaded way.\n"
     234               0 :                      "Try increasing GDAL_MAX_DATASET_POOL_SIZE.", maxSize);
     235               0 :             return NULL;
     236                 :         }
     237                 : 
     238               0 :         CPLFree(lastEntryWithZeroRefCount->pszFileName);
     239               0 :         lastEntryWithZeroRefCount->pszFileName = NULL;
     240               0 :         if (lastEntryWithZeroRefCount->poDS)
     241                 :         {
     242                 :             /* Close by pretending we are the thread that GDALOpen'ed this */
     243                 :             /* dataset */
     244               0 :             GDALSetResponsiblePIDForCurrentThread(lastEntryWithZeroRefCount->responsiblePID);
     245                 : 
     246               0 :             refCountOfDisableRefCount ++;
     247               0 :             GDALClose(lastEntryWithZeroRefCount->poDS);
     248               0 :             refCountOfDisableRefCount --;
     249                 : 
     250               0 :             lastEntryWithZeroRefCount->poDS = NULL;
     251               0 :             GDALSetResponsiblePIDForCurrentThread(responsiblePID);
     252                 :         }
     253                 : 
     254                 :         /* Recycle this entry for the to-be-openeded dataset and */
     255                 :         /* moves it to the top of the list */
     256               0 :         if (lastEntryWithZeroRefCount->prev)
     257               0 :             lastEntryWithZeroRefCount->prev->next = lastEntryWithZeroRefCount->next;
     258                 :         else
     259                 :             CPLAssert(0);
     260               0 :         if (lastEntryWithZeroRefCount->next)
     261               0 :             lastEntryWithZeroRefCount->next->prev = lastEntryWithZeroRefCount->prev;
     262                 :         else
     263                 :         {
     264                 :             CPLAssert(lastEntryWithZeroRefCount == lastEntry);
     265               0 :             lastEntry->prev->next = NULL;
     266               0 :             lastEntry = lastEntry->prev;
     267                 :         }
     268               0 :         lastEntryWithZeroRefCount->prev = NULL;
     269               0 :         lastEntryWithZeroRefCount->next = firstEntry;
     270               0 :         firstEntry->prev = lastEntryWithZeroRefCount;
     271               0 :         cur = firstEntry = lastEntryWithZeroRefCount;
     272                 : #ifdef DEBUG_PROXY_POOL
     273                 :         CheckLinks();
     274                 : #endif
     275                 :     }
     276                 :     else
     277                 :     {
     278                 :         /* Prepend */
     279              51 :         cur = (GDALProxyPoolCacheEntry*) CPLMalloc(sizeof(GDALProxyPoolCacheEntry));
     280              51 :         if (lastEntry == NULL)
     281              25 :             lastEntry = cur;
     282              51 :         cur->prev = NULL;
     283              51 :         cur->next = firstEntry;
     284              51 :         if (firstEntry)
     285              26 :             firstEntry->prev = cur;
     286              51 :         firstEntry = cur;
     287              51 :         currentSize ++;
     288                 : #ifdef DEBUG_PROXY_POOL
     289                 :         CheckLinks();
     290                 : #endif
     291                 :     }
     292                 : 
     293              51 :     cur->pszFileName = CPLStrdup(pszFileName);
     294              51 :     cur->responsiblePID = responsiblePID;
     295              51 :     cur->refCount = 1;
     296                 : 
     297              51 :     refCountOfDisableRefCount ++;
     298              51 :     cur->poDS = (GDALDataset*) GDALOpen(pszFileName, eAccess);
     299              51 :     refCountOfDisableRefCount --;
     300                 : 
     301              51 :     return cur;
     302                 : }
     303                 : 
     304                 : /************************************************************************/
     305                 : /*                                 Ref()                                */
     306                 : /************************************************************************/
     307                 : 
     308             130 : void GDALDatasetPool::Ref()
     309                 : {
     310             130 :     CPLMutexHolderD( GDALGetphDLMutex() );
     311             130 :     if (singleton == NULL)
     312                 :     {
     313              44 :         int maxSize = atoi(CPLGetConfigOption("GDAL_MAX_DATASET_POOL_SIZE", "100"));
     314              44 :         if (maxSize < 2 || maxSize > 1000)
     315               0 :             maxSize = 100;
     316              44 :         singleton = new GDALDatasetPool(maxSize);
     317                 :     }
     318             130 :     if (singleton->refCountOfDisableRefCount == 0)
     319             121 :       singleton->refCount++;
     320             130 : }
     321                 : 
     322                 : /************************************************************************/
     323                 : /*                               Unref()                                */
     324                 : /************************************************************************/
     325                 : 
     326             130 : void GDALDatasetPool::Unref()
     327                 : {
     328             130 :     CPLMutexHolderD( GDALGetphDLMutex() );
     329             130 :     if (! singleton)
     330                 :     {
     331                 :         CPLAssert(0);
     332                 :         return;
     333                 :     }
     334             130 :     if (singleton->refCountOfDisableRefCount == 0)
     335                 :     {
     336             130 :       singleton->refCount--;
     337             130 :       if (singleton->refCount == 0)
     338                 :       {
     339              44 :           delete singleton;
     340              44 :           singleton = NULL;
     341                 :       }
     342               0 :     }
     343                 : }
     344                 : 
     345                 : /************************************************************************/
     346                 : /*                           RefDataset()                               */
     347                 : /************************************************************************/
     348                 : 
     349            4145 : GDALProxyPoolCacheEntry* GDALDatasetPool::RefDataset(const char* pszFileName, GDALAccess eAccess)
     350                 : {
     351            4145 :     CPLMutexHolderD( GDALGetphDLMutex() );
     352            4145 :     return singleton->_RefDataset(pszFileName, eAccess);
     353                 : }
     354                 : 
     355                 : /************************************************************************/
     356                 : /*                       UnrefDataset()                                 */
     357                 : /************************************************************************/
     358                 : 
     359            4145 : void GDALDatasetPool::UnrefDataset(GDALProxyPoolCacheEntry* cacheEntry)
     360                 : {
     361            4145 :     CPLMutexHolderD( GDALGetphDLMutex() );
     362            4145 :     cacheEntry->refCount --;
     363            4145 : }
     364                 : 
     365                 : CPL_C_START
     366                 : 
     367                 : typedef struct
     368                 : {
     369                 :     char* pszDomain;
     370                 :     char** papszMetadata;
     371                 : } GetMetadataElt;
     372                 : 
     373                 : static
     374               0 : unsigned long hash_func_get_metadata(const void* _elt)
     375                 : {
     376               0 :     GetMetadataElt* elt = (GetMetadataElt*) _elt;
     377               0 :     return CPLHashSetHashStr(elt->pszDomain);
     378                 : }
     379                 : 
     380                 : static
     381               0 : int equal_func_get_metadata(const void* _elt1, const void* _elt2)
     382                 : {
     383               0 :     GetMetadataElt* elt1 = (GetMetadataElt*) _elt1;
     384               0 :     GetMetadataElt* elt2 = (GetMetadataElt*) _elt2;
     385               0 :     return CPLHashSetEqualStr(elt1->pszDomain, elt2->pszDomain);
     386                 : }
     387                 : 
     388                 : static
     389               0 : void free_func_get_metadata(void* _elt)
     390                 : {
     391               0 :     GetMetadataElt* elt = (GetMetadataElt*) _elt;
     392               0 :     CPLFree(elt->pszDomain);
     393               0 :     CSLDestroy(elt->papszMetadata);
     394               0 : }
     395                 : 
     396                 : 
     397                 : typedef struct
     398                 : {
     399                 :     char* pszName;
     400                 :     char* pszDomain;
     401                 :     char* pszMetadataItem;
     402                 : } GetMetadataItemElt;
     403                 : 
     404                 : static
     405               0 : unsigned long hash_func_get_metadata_item(const void* _elt)
     406                 : {
     407               0 :     GetMetadataItemElt* elt = (GetMetadataItemElt*) _elt;
     408               0 :     return CPLHashSetHashStr(elt->pszName) ^ CPLHashSetHashStr(elt->pszDomain);
     409                 : }
     410                 : 
     411                 : static
     412               0 : int equal_func_get_metadata_item(const void* _elt1, const void* _elt2)
     413                 : {
     414               0 :     GetMetadataItemElt* elt1 = (GetMetadataItemElt*) _elt1;
     415               0 :     GetMetadataItemElt* elt2 = (GetMetadataItemElt*) _elt2;
     416                 :     return CPLHashSetEqualStr(elt1->pszName, elt2->pszName) &&
     417               0 :            CPLHashSetEqualStr(elt1->pszDomain, elt2->pszDomain);
     418                 : }
     419                 : 
     420                 : static
     421               0 : void free_func_get_metadata_item(void* _elt)
     422                 : {
     423               0 :     GetMetadataItemElt* elt = (GetMetadataItemElt*) _elt;
     424               0 :     CPLFree(elt->pszName);
     425               0 :     CPLFree(elt->pszDomain);
     426               0 :     CPLFree(elt->pszMetadataItem);
     427               0 : }
     428                 : 
     429                 : CPL_C_END
     430                 : 
     431                 : /* ******************************************************************** */
     432                 : /*                     GDALProxyPoolDataset                             */
     433                 : /* ******************************************************************** */
     434                 : 
     435             130 : GDALProxyPoolDataset::GDALProxyPoolDataset(const char* pszSourceDatasetDescription,
     436                 :                                    int nRasterXSize, int nRasterYSize,
     437                 :                                    GDALAccess eAccess, int bShared,
     438                 :                                    const char * pszProjectionRef,
     439             130 :                                    double * padfGeoTransform)
     440                 : {
     441             130 :     GDALDatasetPool::Ref();
     442                 : 
     443             130 :     SetDescription(pszSourceDatasetDescription);
     444                 : 
     445             130 :     this->nRasterXSize = nRasterXSize;
     446             130 :     this->nRasterYSize = nRasterYSize;
     447             130 :     this->eAccess = eAccess;
     448                 : 
     449             130 :     this->bShared = bShared;
     450                 : 
     451             130 :     this->responsiblePID = GDALGetResponsiblePIDForCurrentThread();
     452                 : 
     453             130 :     if (pszProjectionRef)
     454                 :     {
     455              46 :         this->pszProjectionRef = NULL;
     456              46 :         bHasSrcProjection = FALSE;
     457                 :     }
     458                 :     else
     459                 :     {
     460              84 :         this->pszProjectionRef = CPLStrdup(pszProjectionRef);
     461              84 :         bHasSrcProjection = TRUE;
     462                 :     }
     463             130 :     if (padfGeoTransform)
     464                 :     {
     465              38 :         memcpy(adfGeoTransform, padfGeoTransform,6 * sizeof(double));
     466              38 :         bHasSrcGeoTransform = TRUE;
     467                 :     }
     468                 :     else
     469                 :     {
     470              92 :         adfGeoTransform[0] = 0;
     471              92 :         adfGeoTransform[1] = 1;
     472              92 :         adfGeoTransform[2] = 0;
     473              92 :         adfGeoTransform[3] = 0;
     474              92 :         adfGeoTransform[4] = 0;
     475              92 :         adfGeoTransform[5] = 1;
     476              92 :         bHasSrcGeoTransform = FALSE;
     477                 :     }
     478                 : 
     479             130 :     pszGCPProjection = NULL;
     480             130 :     nGCPCount = 0;
     481             130 :     pasGCPList = NULL;
     482             130 :     metadataSet = NULL;
     483             130 :     metadataItemSet = NULL;
     484             130 :     cacheEntry = NULL;
     485             130 : }
     486                 : 
     487                 : /************************************************************************/
     488                 : /*                    ~GDALProxyPoolDataset()                           */
     489                 : /************************************************************************/
     490                 : 
     491             252 : GDALProxyPoolDataset::~GDALProxyPoolDataset()
     492                 : {
     493             130 :     CPLFree(pszProjectionRef);
     494             130 :     CPLFree(pszGCPProjection);
     495             130 :     if (nGCPCount)
     496                 :     {
     497               0 :         GDALDeinitGCPs( nGCPCount, pasGCPList );
     498               0 :         CPLFree( pasGCPList );
     499                 :     }
     500             130 :     if (metadataSet)
     501               0 :         CPLHashSetDestroy(metadataSet);
     502             130 :     if (metadataItemSet)
     503               0 :         CPLHashSetDestroy(metadataItemSet);
     504                 : 
     505             130 :     GDALDatasetPool::Unref();
     506             252 : }
     507                 : 
     508                 : /************************************************************************/
     509                 : /*                    AddSrcBandDescription()                           */
     510                 : /************************************************************************/
     511                 : 
     512             132 : void GDALProxyPoolDataset::AddSrcBandDescription( GDALDataType eDataType, int nBlockXSize, int nBlockYSize)
     513                 : {
     514             132 :     SetBand(nBands + 1, new GDALProxyPoolRasterBand(this, nBands + 1, eDataType, nBlockXSize, nBlockYSize));
     515             132 : }
     516                 : 
     517                 : /************************************************************************/
     518                 : /*                    RefUnderlyingDataset()                            */
     519                 : /************************************************************************/
     520                 : 
     521            4145 : GDALDataset* GDALProxyPoolDataset::RefUnderlyingDataset()
     522                 : {
     523                 :     /* We pretend that the current thread is responsiblePID, that is */
     524                 :     /* to say the thread that created that GDALProxyPoolDataset object. */
     525                 :     /* This is for the case when a GDALProxyPoolDataset is created by a */
     526                 :     /* thread and used by other threads. These other threads, when doing actual */
     527                 :     /* IO, will come there and potentially open the underlying dataset. */
     528                 :     /* By doing this, they can indirectly call GDALOpenShared() on .aux file */
     529                 :     /* for example. So this call to GDALOpenShared() must occur as if it */
     530                 :     /* was done by the creating thread, otherwise it will not be correctly closed afterwards... */
     531                 :     /* To make a long story short : this is necessary when warping with ChunkAndWarpMulti */
     532                 :     /* a VRT of GeoTIFFs that have associated .aux files */
     533            4145 :     GIntBig curResponsiblePID = GDALGetResponsiblePIDForCurrentThread();
     534            4145 :     GDALSetResponsiblePIDForCurrentThread(responsiblePID);
     535            4145 :     cacheEntry = GDALDatasetPool::RefDataset(GetDescription(), eAccess);
     536            4145 :     GDALSetResponsiblePIDForCurrentThread(curResponsiblePID);
     537            4145 :     if (cacheEntry != NULL)
     538                 :     {
     539            4145 :         if (cacheEntry->poDS != NULL)
     540            4144 :             return cacheEntry->poDS;
     541                 :         else
     542               1 :             GDALDatasetPool::UnrefDataset(cacheEntry);
     543                 :     }
     544               1 :     return NULL;
     545                 : }
     546                 : 
     547                 : /************************************************************************/
     548                 : /*                    UnrefUnderlyingDataset()                        */
     549                 : /************************************************************************/
     550                 : 
     551            4144 : void GDALProxyPoolDataset::UnrefUnderlyingDataset(GDALDataset* poUnderlyingDataset)
     552                 : {
     553            4144 :     if (cacheEntry != NULL)
     554                 :     {
     555                 :         CPLAssert(cacheEntry->poDS == poUnderlyingDataset);
     556            4144 :         if (cacheEntry->poDS != NULL)
     557            4144 :             GDALDatasetPool::UnrefDataset(cacheEntry);
     558                 :     }
     559            4144 : }
     560                 : 
     561                 : /************************************************************************/
     562                 : /*                        SetProjection()                               */
     563                 : /************************************************************************/
     564                 : 
     565               0 : CPLErr GDALProxyPoolDataset::SetProjection(const char* pszProjectionRef)
     566                 : {
     567               0 :     bHasSrcProjection = FALSE;
     568               0 :     return GDALProxyDataset::SetProjection(pszProjectionRef);
     569                 : }
     570                 : 
     571                 : /************************************************************************/
     572                 : /*                        GetProjectionRef()                            */
     573                 : /************************************************************************/
     574                 : 
     575               4 : const char *GDALProxyPoolDataset::GetProjectionRef()
     576                 : {
     577               4 :     if (bHasSrcProjection)
     578               0 :         return pszProjectionRef;
     579                 :     else
     580               4 :         return GDALProxyDataset::GetProjectionRef();
     581                 : }
     582                 : 
     583                 : /************************************************************************/
     584                 : /*                        SetGeoTransform()                             */
     585                 : /************************************************************************/
     586                 : 
     587               0 : CPLErr GDALProxyPoolDataset::SetGeoTransform( double * padfGeoTransform )
     588                 : {
     589               0 :     bHasSrcGeoTransform = FALSE;
     590               0 :     return GDALProxyDataset::SetGeoTransform(padfGeoTransform);
     591                 : }
     592                 : 
     593                 : /************************************************************************/
     594                 : /*                        GetGeoTransform()                             */
     595                 : /************************************************************************/
     596                 : 
     597               0 : CPLErr GDALProxyPoolDataset::GetGeoTransform( double * padfGeoTransform )
     598                 : {
     599               0 :     if (bHasSrcGeoTransform)
     600                 :     {
     601               0 :         memcpy(padfGeoTransform, adfGeoTransform, 6 * sizeof(double));
     602               0 :         return CE_None;
     603                 :     }
     604                 :     else
     605                 :     {
     606               0 :         return GDALProxyDataset::GetGeoTransform(padfGeoTransform);
     607                 :     }
     608                 : }
     609                 : 
     610                 : /************************************************************************/
     611                 : /*                            GetMetadata()                             */
     612                 : /************************************************************************/
     613                 : 
     614               0 : char      **GDALProxyPoolDataset::GetMetadata( const char * pszDomain  )
     615                 : {
     616               0 :     if (metadataSet == NULL)
     617                 :         metadataSet = CPLHashSetNew(hash_func_get_metadata,
     618                 :                                     equal_func_get_metadata,
     619               0 :                                     free_func_get_metadata);
     620                 : 
     621               0 :     GDALDataset* poUnderlyingDataset = RefUnderlyingDataset();
     622               0 :     if (poUnderlyingDataset == NULL)
     623               0 :         return NULL;
     624                 : 
     625               0 :     char** papszUnderlyingMetadata = poUnderlyingDataset->GetMetadata(pszDomain);
     626                 : 
     627               0 :     GetMetadataElt* pElt = (GetMetadataElt*) CPLMalloc(sizeof(GetMetadataElt));
     628               0 :     pElt->pszDomain = (pszDomain) ? CPLStrdup(pszDomain) : NULL;
     629               0 :     pElt->papszMetadata = CSLDuplicate(papszUnderlyingMetadata);
     630               0 :     CPLHashSetInsert(metadataSet, pElt);
     631                 : 
     632               0 :     UnrefUnderlyingDataset(poUnderlyingDataset);
     633                 : 
     634               0 :     return pElt->papszMetadata;
     635                 : }
     636                 : 
     637                 : /************************************************************************/
     638                 : /*                        GetMetadataItem()                             */
     639                 : /************************************************************************/
     640                 : 
     641               0 : const char *GDALProxyPoolDataset::GetMetadataItem( const char * pszName,
     642                 :                                                    const char * pszDomain  )
     643                 : {
     644               0 :     if (metadataItemSet == NULL)
     645                 :         metadataItemSet = CPLHashSetNew(hash_func_get_metadata_item,
     646                 :                                         equal_func_get_metadata_item,
     647               0 :                                         free_func_get_metadata_item);
     648                 : 
     649               0 :     GDALDataset* poUnderlyingDataset = RefUnderlyingDataset();
     650               0 :     if (poUnderlyingDataset == NULL)
     651               0 :         return NULL;
     652                 : 
     653                 :     const char* pszUnderlyingMetadataItem =
     654               0 :             poUnderlyingDataset->GetMetadataItem(pszName, pszDomain);
     655                 : 
     656               0 :     GetMetadataItemElt* pElt = (GetMetadataItemElt*) CPLMalloc(sizeof(GetMetadataItemElt));
     657               0 :     pElt->pszName = (pszName) ? CPLStrdup(pszName) : NULL;
     658               0 :     pElt->pszDomain = (pszDomain) ? CPLStrdup(pszDomain) : NULL;
     659               0 :     pElt->pszMetadataItem = (pszUnderlyingMetadataItem) ? CPLStrdup(pszUnderlyingMetadataItem) : NULL;
     660               0 :     CPLHashSetInsert(metadataItemSet, pElt);
     661                 : 
     662               0 :     UnrefUnderlyingDataset(poUnderlyingDataset);
     663                 : 
     664               0 :     return pElt->pszMetadataItem;
     665                 : }
     666                 : 
     667                 : /************************************************************************/
     668                 : /*                      GetInternalHandle()                             */
     669                 : /************************************************************************/
     670                 : 
     671               0 : void *GDALProxyPoolDataset::GetInternalHandle( const char * pszRequest)
     672                 : {
     673                 :     CPLError(CE_Warning, CPLE_AppDefined,
     674                 :              "GetInternalHandle() cannot be safely called on a proxy pool dataset\n"
     675               0 :              "as the returned value may be invalidated at any time.\n");
     676               0 :     return GDALProxyDataset::GetInternalHandle(pszRequest);
     677                 : }
     678                 : 
     679                 : /************************************************************************/
     680                 : /*                     GetGCPProjection()                               */
     681                 : /************************************************************************/
     682                 : 
     683               0 : const char *GDALProxyPoolDataset::GetGCPProjection()
     684                 : {
     685               0 :     GDALDataset* poUnderlyingDataset = RefUnderlyingDataset();
     686               0 :     if (poUnderlyingDataset == NULL)
     687               0 :         return NULL;
     688                 : 
     689               0 :     CPLFree(pszGCPProjection);
     690               0 :     pszGCPProjection = NULL;
     691                 : 
     692               0 :     const char* pszUnderlyingGCPProjection = poUnderlyingDataset->GetGCPProjection();
     693               0 :     if (pszUnderlyingGCPProjection)
     694               0 :         pszGCPProjection = CPLStrdup(pszUnderlyingGCPProjection);
     695                 : 
     696               0 :     UnrefUnderlyingDataset(poUnderlyingDataset);
     697                 : 
     698               0 :     return pszGCPProjection;
     699                 : }
     700                 : 
     701                 : /************************************************************************/
     702                 : /*                            GetGCPs()                                 */
     703                 : /************************************************************************/
     704                 : 
     705               0 : const GDAL_GCP *GDALProxyPoolDataset::GetGCPs()
     706                 : {
     707               0 :     GDALDataset* poUnderlyingDataset = RefUnderlyingDataset();
     708               0 :     if (poUnderlyingDataset == NULL)
     709               0 :         return NULL;
     710                 : 
     711               0 :     if (nGCPCount)
     712                 :     {
     713               0 :         GDALDeinitGCPs( nGCPCount, pasGCPList );
     714               0 :         CPLFree( pasGCPList );
     715               0 :         pasGCPList = NULL;
     716                 :     }
     717                 : 
     718               0 :     const GDAL_GCP* pasUnderlyingGCPList = poUnderlyingDataset->GetGCPs();
     719               0 :     nGCPCount = poUnderlyingDataset->GetGCPCount();
     720               0 :     if (nGCPCount)
     721               0 :         pasGCPList = GDALDuplicateGCPs(nGCPCount, pasUnderlyingGCPList );
     722                 : 
     723               0 :     UnrefUnderlyingDataset(poUnderlyingDataset);
     724                 : 
     725               0 :     return pasGCPList;
     726                 : }
     727                 : 
     728                 : /************************************************************************/
     729                 : /*                     GDALProxyPoolDatasetCreate()                     */
     730                 : /************************************************************************/
     731                 : 
     732              38 : GDALProxyPoolDatasetH GDALProxyPoolDatasetCreate(const char* pszSourceDatasetDescription,
     733                 :                                                  int nRasterXSize, int nRasterYSize,
     734                 :                                                  GDALAccess eAccess, int bShared,
     735                 :                                                  const char * pszProjectionRef,
     736                 :                                                  double * padfGeoTransform)
     737                 : {
     738                 :     return (GDALProxyPoolDatasetH)
     739                 :            new GDALProxyPoolDataset(pszSourceDatasetDescription,
     740                 :                                     nRasterXSize, nRasterYSize,
     741                 :                                     eAccess, bShared,
     742              38 :                                     pszProjectionRef, padfGeoTransform);
     743                 : }
     744                 : 
     745                 : /************************************************************************/
     746                 : /*                       GDALProxyPoolDatasetDelete()                   */
     747                 : /************************************************************************/
     748                 : 
     749               0 : void CPL_DLL GDALProxyPoolDatasetDelete(GDALProxyPoolDatasetH hProxyPoolDataset)
     750                 : {
     751               0 :     delete (GDALProxyPoolDataset*)hProxyPoolDataset;
     752               0 : }
     753                 : 
     754                 : /************************************************************************/
     755                 : /*              GDALProxyPoolDatasetAddSrcBandDescription()             */
     756                 : /************************************************************************/
     757                 : 
     758              42 : void GDALProxyPoolDatasetAddSrcBandDescription( GDALProxyPoolDatasetH hProxyPoolDataset,
     759                 :                                                 GDALDataType eDataType,
     760                 :                                                 int nBlockXSize, int nBlockYSize)
     761                 : {
     762                 :     ((GDALProxyPoolDataset*)hProxyPoolDataset)->
     763              42 :             AddSrcBandDescription(eDataType, nBlockXSize, nBlockYSize);
     764              42 : }
     765                 : 
     766                 : /* ******************************************************************** */
     767                 : /*                    GDALProxyPoolRasterBand()                         */
     768                 : /* ******************************************************************** */
     769                 : 
     770             132 : GDALProxyPoolRasterBand::GDALProxyPoolRasterBand(GDALProxyPoolDataset* poDS, int nBand,
     771                 :                                                  GDALDataType eDataType,
     772             132 :                                                  int nBlockXSize, int nBlockYSize)
     773                 : {
     774             132 :     this->poDS         = poDS;
     775             132 :     this->nBand        = nBand;
     776             132 :     this->eDataType    = eDataType;
     777             132 :     this->nRasterXSize = poDS->GetRasterXSize();
     778             132 :     this->nRasterYSize = poDS->GetRasterYSize();
     779             132 :     this->nBlockXSize  = nBlockXSize;
     780             132 :     this->nBlockYSize  = nBlockYSize;
     781                 : 
     782             132 :     Init();
     783             132 : }
     784                 : 
     785                 : /* ******************************************************************** */
     786                 : /*                    GDALProxyPoolRasterBand()                         */
     787                 : /* ******************************************************************** */
     788                 : 
     789               0 : GDALProxyPoolRasterBand::GDALProxyPoolRasterBand(GDALProxyPoolDataset* poDS,
     790               0 :                                                  GDALRasterBand* poUnderlyingRasterBand)
     791                 : {
     792               0 :     this->poDS         = poDS;
     793               0 :     this->nBand        = poUnderlyingRasterBand->GetBand();
     794               0 :     this->eDataType    = poUnderlyingRasterBand->GetRasterDataType();
     795               0 :     this->nRasterXSize = poUnderlyingRasterBand->GetXSize();
     796               0 :     this->nRasterYSize = poUnderlyingRasterBand->GetYSize();
     797               0 :     poUnderlyingRasterBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
     798                 : 
     799               0 :     Init();
     800               0 : }
     801                 : 
     802                 : /* ******************************************************************** */
     803                 :  /*                                  Init()                             */
     804                 : /* ******************************************************************** */
     805                 : 
     806             132 : void GDALProxyPoolRasterBand::Init()
     807                 : {
     808             132 :     metadataSet = NULL;
     809             132 :     metadataItemSet = NULL;
     810             132 :     pszUnitType = NULL;
     811             132 :     papszCategoryNames = NULL;
     812             132 :     poColorTable = NULL;
     813                 : 
     814             132 :     nSizeProxyOverviewRasterBand = 0;
     815             132 :     papoProxyOverviewRasterBand = NULL;
     816             132 :     poProxyMaskBand = NULL;
     817             132 : }
     818                 : 
     819                 : /* ******************************************************************** */
     820                 : /*                   ~GDALProxyPoolRasterBand()                         */
     821                 : /* ******************************************************************** */
     822             264 : GDALProxyPoolRasterBand::~GDALProxyPoolRasterBand()
     823                 : {
     824             132 :     if (metadataSet)
     825               0 :         CPLHashSetDestroy(metadataSet);
     826             132 :     if (metadataItemSet)
     827               0 :         CPLHashSetDestroy(metadataItemSet);
     828             132 :     CPLFree(pszUnitType);
     829             132 :     CSLDestroy(papszCategoryNames);
     830             132 :     if (poColorTable)
     831               7 :         delete poColorTable;
     832                 : 
     833                 :     int i;
     834             132 :     for(i=0;i<nSizeProxyOverviewRasterBand;i++)
     835                 :     {
     836               0 :         if (papoProxyOverviewRasterBand[i])
     837               0 :             delete papoProxyOverviewRasterBand[i];
     838                 :     }
     839             132 :     CPLFree(papoProxyOverviewRasterBand);
     840             132 :     if (poProxyMaskBand)
     841               0 :         delete poProxyMaskBand;
     842             264 : }
     843                 : 
     844                 : 
     845                 : /************************************************************************/
     846                 : /*                  RefUnderlyingRasterBand()                           */
     847                 : /************************************************************************/
     848                 : 
     849            3781 : GDALRasterBand* GDALProxyPoolRasterBand::RefUnderlyingRasterBand()
     850                 : {
     851            3781 :     GDALDataset* poUnderlyingDataset = ((GDALProxyPoolDataset*)poDS)->RefUnderlyingDataset();
     852            3781 :     if (poUnderlyingDataset == NULL)
     853               1 :         return NULL;
     854                 : 
     855            3780 :     return poUnderlyingDataset->GetRasterBand(nBand);
     856                 : }
     857                 : 
     858                 : /************************************************************************/
     859                 : /*                  UnrefUnderlyingRasterBand()                       */
     860                 : /************************************************************************/
     861                 : 
     862            3780 : void GDALProxyPoolRasterBand::UnrefUnderlyingRasterBand(GDALRasterBand* poUnderlyingRasterBand)
     863                 : {
     864            3780 :     if (poUnderlyingRasterBand)
     865            3780 :         ((GDALProxyPoolDataset*)poDS)->UnrefUnderlyingDataset(poUnderlyingRasterBand->GetDataset());
     866            3780 : }
     867                 : 
     868                 : /************************************************************************/
     869                 : /*                            GetMetadata()                             */
     870                 : /************************************************************************/
     871                 : 
     872               0 : char      **GDALProxyPoolRasterBand::GetMetadata( const char * pszDomain  )
     873                 : {
     874               0 :     if (metadataSet == NULL)
     875                 :         metadataSet = CPLHashSetNew(hash_func_get_metadata,
     876                 :                                     equal_func_get_metadata,
     877               0 :                                     free_func_get_metadata);
     878                 : 
     879               0 :     GDALRasterBand* poUnderlyingRasterBand = RefUnderlyingRasterBand();
     880               0 :     if (poUnderlyingRasterBand == NULL)
     881               0 :         return NULL;
     882                 : 
     883               0 :     char** papszUnderlyingMetadata = poUnderlyingRasterBand->GetMetadata(pszDomain);
     884                 : 
     885               0 :     GetMetadataElt* pElt = (GetMetadataElt*) CPLMalloc(sizeof(GetMetadataElt));
     886               0 :     pElt->pszDomain = (pszDomain) ? CPLStrdup(pszDomain) : NULL;
     887               0 :     pElt->papszMetadata = CSLDuplicate(papszUnderlyingMetadata);
     888               0 :     CPLHashSetInsert(metadataSet, pElt);
     889                 : 
     890               0 :     UnrefUnderlyingRasterBand(poUnderlyingRasterBand);
     891                 : 
     892               0 :     return pElt->papszMetadata;
     893                 : }
     894                 : 
     895                 : /************************************************************************/
     896                 : /*                        GetMetadataItem()                             */
     897                 : /************************************************************************/
     898                 : 
     899               0 : const char *GDALProxyPoolRasterBand::GetMetadataItem( const char * pszName,
     900                 :                                                    const char * pszDomain  )
     901                 : {
     902               0 :     if (metadataItemSet == NULL)
     903                 :         metadataItemSet = CPLHashSetNew(hash_func_get_metadata_item,
     904                 :                                         equal_func_get_metadata_item,
     905               0 :                                         free_func_get_metadata_item);
     906                 : 
     907               0 :     GDALRasterBand* poUnderlyingRasterBand = RefUnderlyingRasterBand();
     908               0 :     if (poUnderlyingRasterBand == NULL)
     909               0 :         return NULL;
     910                 : 
     911                 :     const char* pszUnderlyingMetadataItem =
     912               0 :             poUnderlyingRasterBand->GetMetadataItem(pszName, pszDomain);
     913                 : 
     914               0 :     GetMetadataItemElt* pElt = (GetMetadataItemElt*) CPLMalloc(sizeof(GetMetadataItemElt));
     915               0 :     pElt->pszName = (pszName) ? CPLStrdup(pszName) : NULL;
     916               0 :     pElt->pszDomain = (pszDomain) ? CPLStrdup(pszDomain) : NULL;
     917               0 :     pElt->pszMetadataItem = (pszUnderlyingMetadataItem) ? CPLStrdup(pszUnderlyingMetadataItem) : NULL;
     918               0 :     CPLHashSetInsert(metadataItemSet, pElt);
     919                 : 
     920               0 :     UnrefUnderlyingRasterBand(poUnderlyingRasterBand);
     921                 : 
     922               0 :     return pElt->pszMetadataItem;
     923                 : }
     924                 : 
     925                 : /* ******************************************************************** */
     926                 : /*                       GetCategoryNames()                             */
     927                 : /* ******************************************************************** */
     928                 : 
     929               0 : char **GDALProxyPoolRasterBand::GetCategoryNames()
     930                 : {
     931               0 :     GDALRasterBand* poUnderlyingRasterBand = RefUnderlyingRasterBand();
     932               0 :     if (poUnderlyingRasterBand == NULL)
     933               0 :         return NULL;
     934                 : 
     935               0 :     CSLDestroy(papszCategoryNames);
     936               0 :     papszCategoryNames = NULL;
     937                 : 
     938               0 :     char** papszUnderlyingCategoryNames = poUnderlyingRasterBand->GetCategoryNames();
     939               0 :     if (papszUnderlyingCategoryNames)
     940               0 :         papszCategoryNames = CSLDuplicate(papszUnderlyingCategoryNames);
     941                 : 
     942               0 :     UnrefUnderlyingRasterBand(poUnderlyingRasterBand);
     943                 : 
     944               0 :     return papszCategoryNames;
     945                 : }
     946                 : 
     947                 : /* ******************************************************************** */
     948                 : /*                           GetUnitType()                              */
     949                 : /* ******************************************************************** */
     950                 : 
     951               0 : const char *GDALProxyPoolRasterBand::GetUnitType()
     952                 : {
     953               0 :     GDALRasterBand* poUnderlyingRasterBand = RefUnderlyingRasterBand();
     954               0 :     if (poUnderlyingRasterBand == NULL)
     955               0 :         return NULL;
     956                 : 
     957               0 :     CPLFree(pszUnitType);
     958               0 :     pszUnitType = NULL;
     959                 : 
     960               0 :     const char* pszUnderlyingUnitType = poUnderlyingRasterBand->GetUnitType();
     961               0 :     if (pszUnderlyingUnitType)
     962               0 :         pszUnitType = CPLStrdup(pszUnderlyingUnitType);
     963                 : 
     964               0 :     UnrefUnderlyingRasterBand(poUnderlyingRasterBand);
     965                 : 
     966               0 :     return pszUnitType;
     967                 : }
     968                 : 
     969                 : /* ******************************************************************** */
     970                 : /*                          GetColorTable()                             */
     971                 : /* ******************************************************************** */
     972                 : 
     973            1603 : GDALColorTable *GDALProxyPoolRasterBand::GetColorTable()
     974                 : {
     975            1603 :     GDALRasterBand* poUnderlyingRasterBand = RefUnderlyingRasterBand();
     976            1603 :     if (poUnderlyingRasterBand == NULL)
     977               0 :         return NULL;
     978                 : 
     979            1603 :     if (poColorTable)
     980            1596 :         delete poColorTable;
     981            1603 :     poColorTable = NULL;
     982                 : 
     983            1603 :     GDALColorTable* poUnderlyingColorTable = poUnderlyingRasterBand->GetColorTable();
     984            1603 :     if (poUnderlyingColorTable)
     985            1603 :         poColorTable = poUnderlyingColorTable->Clone();
     986                 : 
     987            1603 :     UnrefUnderlyingRasterBand(poUnderlyingRasterBand);
     988                 : 
     989            1603 :     return poColorTable;
     990                 : }
     991                 : 
     992                 : /* ******************************************************************** */
     993                 : /*                           GetOverview()                              */
     994                 : /* ******************************************************************** */
     995                 : 
     996               0 : GDALRasterBand *GDALProxyPoolRasterBand::GetOverview(int nOverviewBand)
     997                 : {
     998               0 :     if (nOverviewBand >= 0 && nOverviewBand < nSizeProxyOverviewRasterBand)
     999                 :     {
    1000               0 :         if (papoProxyOverviewRasterBand[nOverviewBand])
    1001               0 :             return papoProxyOverviewRasterBand[nOverviewBand];
    1002                 :     }
    1003                 : 
    1004               0 :     GDALRasterBand* poUnderlyingRasterBand = RefUnderlyingRasterBand();
    1005               0 :     if (poUnderlyingRasterBand == NULL)
    1006               0 :         return NULL;
    1007                 : 
    1008               0 :     GDALRasterBand* poOverviewRasterBand = poUnderlyingRasterBand->GetOverview(nOverviewBand);
    1009               0 :     if (poOverviewRasterBand == NULL)
    1010                 :     {
    1011               0 :         UnrefUnderlyingRasterBand(poUnderlyingRasterBand);
    1012               0 :         return NULL;
    1013                 :     }
    1014                 : 
    1015               0 :     if (nOverviewBand >= nSizeProxyOverviewRasterBand)
    1016                 :     {
    1017                 :         int i;
    1018                 :         papoProxyOverviewRasterBand = (GDALProxyPoolOverviewRasterBand**)
    1019                 :                 CPLRealloc(papoProxyOverviewRasterBand,
    1020               0 :                         sizeof(GDALProxyPoolOverviewRasterBand*) * (nOverviewBand + 1));
    1021               0 :         for(i=nSizeProxyOverviewRasterBand; i<nOverviewBand + 1;i++)
    1022               0 :             papoProxyOverviewRasterBand[i] = NULL;
    1023               0 :         nSizeProxyOverviewRasterBand = nOverviewBand + 1;
    1024                 :     }
    1025                 : 
    1026               0 :     papoProxyOverviewRasterBand[nOverviewBand] =
    1027                 :             new GDALProxyPoolOverviewRasterBand((GDALProxyPoolDataset*)poDS,
    1028                 :                                                 poOverviewRasterBand,
    1029               0 :                                                 this, nOverviewBand);
    1030                 : 
    1031               0 :     UnrefUnderlyingRasterBand(poUnderlyingRasterBand);
    1032                 : 
    1033               0 :     return papoProxyOverviewRasterBand[nOverviewBand];
    1034                 : }
    1035                 : 
    1036                 : /* ******************************************************************** */
    1037                 : /*                     GetRasterSampleOverview()                        */
    1038                 : /* ******************************************************************** */
    1039                 : 
    1040               0 : GDALRasterBand *GDALProxyPoolRasterBand::GetRasterSampleOverview( int nDesiredSamples)
    1041                 : {
    1042                 :     CPLError(CE_Failure, CPLE_AppDefined,
    1043               0 :              "GDALProxyPoolRasterBand::GetRasterSampleOverview : not implemented yet");
    1044               0 :     return NULL;
    1045                 : }
    1046                 : 
    1047                 : /* ******************************************************************** */
    1048                 : /*                           GetMaskBand()                              */
    1049                 : /* ******************************************************************** */
    1050                 : 
    1051               0 : GDALRasterBand *GDALProxyPoolRasterBand::GetMaskBand()
    1052                 : {
    1053               0 :     if (poProxyMaskBand)
    1054               0 :         return poProxyMaskBand;
    1055                 : 
    1056               0 :     GDALRasterBand* poUnderlyingRasterBand = RefUnderlyingRasterBand();
    1057               0 :     if (poUnderlyingRasterBand == NULL)
    1058               0 :         return NULL;
    1059                 : 
    1060               0 :     GDALRasterBand* poMaskBand = poUnderlyingRasterBand->GetMaskBand();
    1061                 : 
    1062                 :     poProxyMaskBand =
    1063                 :             new GDALProxyPoolMaskBand((GDALProxyPoolDataset*)poDS,
    1064                 :                                        poMaskBand,
    1065               0 :                                        this);
    1066                 : 
    1067               0 :     UnrefUnderlyingRasterBand(poUnderlyingRasterBand);
    1068                 : 
    1069               0 :     return poProxyMaskBand;
    1070                 : }
    1071                 : 
    1072                 : /* ******************************************************************** */
    1073                 : /*             GDALProxyPoolOverviewRasterBand()                        */
    1074                 : /* ******************************************************************** */
    1075                 : 
    1076               0 : GDALProxyPoolOverviewRasterBand::GDALProxyPoolOverviewRasterBand(GDALProxyPoolDataset* poDS,
    1077                 :                                                                  GDALRasterBand* poUnderlyingOverviewBand,
    1078                 :                                                                  GDALProxyPoolRasterBand* poMainBand,
    1079                 :                                                                  int nOverviewBand) :
    1080               0 :         GDALProxyPoolRasterBand(poDS, poUnderlyingOverviewBand)
    1081                 : {
    1082               0 :     this->poMainBand = poMainBand;
    1083               0 :     this->nOverviewBand = nOverviewBand;
    1084                 : 
    1085               0 :     poUnderlyingMainRasterBand = NULL;
    1086               0 :     nRefCountUnderlyingMainRasterBand = 0;
    1087               0 : }
    1088                 : 
    1089                 : /* ******************************************************************** */
    1090                 : /*                  ~GDALProxyPoolOverviewRasterBand()                  */
    1091                 : /* ******************************************************************** */
    1092                 : 
    1093               0 : GDALProxyPoolOverviewRasterBand::~GDALProxyPoolOverviewRasterBand()
    1094                 : {
    1095                 :     CPLAssert(nRefCountUnderlyingMainRasterBand == 0);
    1096               0 : }
    1097                 : 
    1098                 : /* ******************************************************************** */
    1099                 : /*                    RefUnderlyingRasterBand()                         */
    1100                 : /* ******************************************************************** */
    1101                 : 
    1102               0 : GDALRasterBand* GDALProxyPoolOverviewRasterBand::RefUnderlyingRasterBand()
    1103                 : {
    1104               0 :     poUnderlyingMainRasterBand = poMainBand->RefUnderlyingRasterBand();
    1105               0 :     if (poUnderlyingMainRasterBand == NULL)
    1106               0 :         return NULL;
    1107                 : 
    1108               0 :     nRefCountUnderlyingMainRasterBand ++;
    1109               0 :     return poUnderlyingMainRasterBand->GetOverview(nOverviewBand);
    1110                 : }
    1111                 : 
    1112                 : /* ******************************************************************** */
    1113                 : /*                  UnrefUnderlyingRasterBand()                         */
    1114                 : /* ******************************************************************** */
    1115                 : 
    1116               0 : void GDALProxyPoolOverviewRasterBand::UnrefUnderlyingRasterBand(GDALRasterBand* poUnderlyingRasterBand)
    1117                 : {
    1118               0 :     poMainBand->UnrefUnderlyingRasterBand(poUnderlyingMainRasterBand);
    1119               0 :     nRefCountUnderlyingMainRasterBand --;
    1120               0 : }
    1121                 : 
    1122                 : 
    1123                 : /* ******************************************************************** */
    1124                 : /*                     GDALProxyPoolMaskBand()                          */
    1125                 : /* ******************************************************************** */
    1126                 : 
    1127               0 : GDALProxyPoolMaskBand::GDALProxyPoolMaskBand(GDALProxyPoolDataset* poDS,
    1128                 :                                              GDALRasterBand* poUnderlyingMaskBand,
    1129                 :                                              GDALProxyPoolRasterBand* poMainBand) :
    1130               0 :         GDALProxyPoolRasterBand(poDS, poUnderlyingMaskBand)
    1131                 : {
    1132               0 :     this->poMainBand = poMainBand;
    1133                 : 
    1134               0 :     poUnderlyingMainRasterBand = NULL;
    1135               0 :     nRefCountUnderlyingMainRasterBand = 0;
    1136               0 : }
    1137                 : 
    1138                 : /* ******************************************************************** */
    1139                 : /*                          ~GDALProxyPoolMaskBand()                    */
    1140                 : /* ******************************************************************** */
    1141                 : 
    1142               0 : GDALProxyPoolMaskBand::~GDALProxyPoolMaskBand()
    1143                 : {
    1144                 :     CPLAssert(nRefCountUnderlyingMainRasterBand == 0);
    1145               0 : }
    1146                 : 
    1147                 : /* ******************************************************************** */
    1148                 : /*                    RefUnderlyingRasterBand()                         */
    1149                 : /* ******************************************************************** */
    1150                 : 
    1151               0 : GDALRasterBand* GDALProxyPoolMaskBand::RefUnderlyingRasterBand()
    1152                 : {
    1153               0 :     poUnderlyingMainRasterBand = poMainBand->RefUnderlyingRasterBand();
    1154               0 :     if (poUnderlyingMainRasterBand == NULL)
    1155               0 :         return NULL;
    1156                 : 
    1157               0 :     nRefCountUnderlyingMainRasterBand ++;
    1158               0 :     return poUnderlyingMainRasterBand->GetMaskBand();
    1159                 : }
    1160                 : 
    1161                 : /* ******************************************************************** */
    1162                 : /*                  UnrefUnderlyingRasterBand()                         */
    1163                 : /* ******************************************************************** */
    1164                 : 
    1165               0 : void GDALProxyPoolMaskBand::UnrefUnderlyingRasterBand(GDALRasterBand* poUnderlyingRasterBand)
    1166                 : {
    1167               0 :     poMainBand->UnrefUnderlyingRasterBand(poUnderlyingMainRasterBand);
    1168               0 :     nRefCountUnderlyingMainRasterBand --;
    1169               0 : }

Generated by: LCOV version 1.7