LCOV - code coverage report
Current view: directory - gcore - gdalproxypool.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 517 243 47.0 %
Date: 2013-03-30 Functions: 77 35 45.5 %

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

Generated by: LCOV version 1.7