LCOV - code coverage report
Current view: directory - gcore - gdalproxypool.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 516 243 47.1 %
Date: 2012-12-26 Functions: 76 35 46.1 %

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

Generated by: LCOV version 1.7