mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-31 14:22:38 -06:00
1335 lines
48 KiB
C++
1335 lines
48 KiB
C++
/******************************************************************************
|
|
* $Id: gdalproxypool.cpp 29326 2015-06-10 20:36:31Z rouault $
|
|
*
|
|
* Project: GDAL Core
|
|
* Purpose: A dataset and raster band classes that differ the opening of the
|
|
* underlying dataset in a limited pool of opened datasets.
|
|
* Author: Even Rouault <even dot rouault at mines dash paris dot org>
|
|
*
|
|
******************************************************************************
|
|
* Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included
|
|
* in all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
****************************************************************************/
|
|
|
|
#include "gdal_proxy.h"
|
|
#include "cpl_multiproc.h"
|
|
|
|
CPL_CVSID("$Id: gdalproxypool.cpp 29326 2015-06-10 20:36:31Z rouault $");
|
|
|
|
/* We *must* share the same mutex as the gdaldataset.cpp file, as we are */
|
|
/* doing GDALOpen() calls that can indirectly call GDALOpenShared() on */
|
|
/* an auxiliary dataset ... */
|
|
/* Then we could get dead-locks in multi-threaded use case */
|
|
|
|
/* ******************************************************************** */
|
|
/* GDALDatasetPool */
|
|
/* ******************************************************************** */
|
|
|
|
/* This class is a singleton that maintains a pool of opened datasets */
|
|
/* The cache uses a LRU strategy */
|
|
|
|
class GDALDatasetPool;
|
|
static GDALDatasetPool* singleton = NULL;
|
|
|
|
void GDALNullifyProxyPoolSingleton() { singleton = NULL; }
|
|
|
|
struct _GDALProxyPoolCacheEntry
|
|
{
|
|
GIntBig responsiblePID;
|
|
char *pszFileName;
|
|
GDALDataset *poDS;
|
|
|
|
/* Ref count of the cached dataset */
|
|
int refCount;
|
|
|
|
GDALProxyPoolCacheEntry* prev;
|
|
GDALProxyPoolCacheEntry* next;
|
|
};
|
|
|
|
class GDALDatasetPool
|
|
{
|
|
private:
|
|
/* Ref count of the pool singleton */
|
|
/* Taken by "toplevel" GDALProxyPoolDataset in its constructor and released */
|
|
/* in its destructor. See also refCountOfDisableRefCount for the difference */
|
|
/* between toplevel and inner GDALProxyPoolDataset */
|
|
int refCount;
|
|
|
|
int maxSize;
|
|
int currentSize;
|
|
GDALProxyPoolCacheEntry* firstEntry;
|
|
GDALProxyPoolCacheEntry* lastEntry;
|
|
|
|
/* This variable prevents a dataset that is going to be opened in GDALDatasetPool::_RefDataset */
|
|
/* from increasing refCount if, during its opening, it creates a GDALProxyPoolDataset */
|
|
/* We increment it before opening or closing a cached dataset and decrement it afterwards */
|
|
/* The typical use case is a VRT made of simple sources that are VRT */
|
|
/* We don't want the "inner" VRT to take a reference on the pool, otherwise there is */
|
|
/* a high chance that this reference will not be dropped and the pool remain ghost */
|
|
int refCountOfDisableRefCount;
|
|
|
|
/* Caution : to be sure that we don't run out of entries, size must be at */
|
|
/* least greater or equal than the maximum number of threads */
|
|
GDALDatasetPool(int maxSize);
|
|
~GDALDatasetPool();
|
|
GDALProxyPoolCacheEntry* _RefDataset(const char* pszFileName,
|
|
GDALAccess eAccess,
|
|
char** papszOpenOptions,
|
|
int bShared);
|
|
void _CloseDataset(const char* pszFileName, GDALAccess eAccess);
|
|
|
|
void ShowContent();
|
|
void CheckLinks();
|
|
|
|
public:
|
|
static void Ref();
|
|
static void Unref();
|
|
static GDALProxyPoolCacheEntry* RefDataset(const char* pszFileName,
|
|
GDALAccess eAccess,
|
|
char** papszOpenOptions,
|
|
int bShared);
|
|
static void UnrefDataset(GDALProxyPoolCacheEntry* cacheEntry);
|
|
static void CloseDataset(const char* pszFileName, GDALAccess eAccess);
|
|
|
|
static void PreventDestroy();
|
|
static void ForceDestroy();
|
|
};
|
|
|
|
|
|
/************************************************************************/
|
|
/* GDALDatasetPool() */
|
|
/************************************************************************/
|
|
|
|
GDALDatasetPool::GDALDatasetPool(int maxSize)
|
|
{
|
|
this->maxSize = maxSize;
|
|
currentSize = 0;
|
|
firstEntry = NULL;
|
|
lastEntry = NULL;
|
|
refCount = 0;
|
|
refCountOfDisableRefCount = 0;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* ~GDALDatasetPool() */
|
|
/************************************************************************/
|
|
|
|
GDALDatasetPool::~GDALDatasetPool()
|
|
{
|
|
GDALProxyPoolCacheEntry* cur = firstEntry;
|
|
GIntBig responsiblePID = GDALGetResponsiblePIDForCurrentThread();
|
|
while(cur)
|
|
{
|
|
GDALProxyPoolCacheEntry* next = cur->next;
|
|
CPLFree(cur->pszFileName);
|
|
CPLAssert(cur->refCount == 0);
|
|
if (cur->poDS)
|
|
{
|
|
GDALSetResponsiblePIDForCurrentThread(cur->responsiblePID);
|
|
GDALClose(cur->poDS);
|
|
}
|
|
CPLFree(cur);
|
|
cur = next;
|
|
}
|
|
GDALSetResponsiblePIDForCurrentThread(responsiblePID);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* ShowContent() */
|
|
/************************************************************************/
|
|
|
|
void GDALDatasetPool::ShowContent()
|
|
{
|
|
GDALProxyPoolCacheEntry* cur = firstEntry;
|
|
int i = 0;
|
|
while(cur)
|
|
{
|
|
printf("[%d] pszFileName=%s, refCount=%d, responsiblePID=%d\n",
|
|
i, cur->pszFileName, cur->refCount, (int)cur->responsiblePID);
|
|
i++;
|
|
cur = cur->next;
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* CheckLinks() */
|
|
/************************************************************************/
|
|
|
|
void GDALDatasetPool::CheckLinks()
|
|
{
|
|
GDALProxyPoolCacheEntry* cur = firstEntry;
|
|
int i = 0;
|
|
while(cur)
|
|
{
|
|
CPLAssert(cur == firstEntry || cur->prev->next == cur);
|
|
CPLAssert(cur == lastEntry || cur->next->prev == cur);
|
|
i++;
|
|
CPLAssert(cur->next != NULL || cur == lastEntry);
|
|
cur = cur->next;
|
|
}
|
|
CPLAssert(i == currentSize);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* _RefDataset() */
|
|
/************************************************************************/
|
|
|
|
GDALProxyPoolCacheEntry* GDALDatasetPool::_RefDataset(const char* pszFileName,
|
|
GDALAccess eAccess,
|
|
char** papszOpenOptions,
|
|
int bShared)
|
|
{
|
|
GDALProxyPoolCacheEntry* cur = firstEntry;
|
|
GIntBig responsiblePID = GDALGetResponsiblePIDForCurrentThread();
|
|
GDALProxyPoolCacheEntry* lastEntryWithZeroRefCount = NULL;
|
|
|
|
while(cur)
|
|
{
|
|
GDALProxyPoolCacheEntry* next = cur->next;
|
|
|
|
if (strcmp(cur->pszFileName, pszFileName) == 0 &&
|
|
((bShared && cur->responsiblePID == responsiblePID) ||
|
|
(!bShared && cur->refCount == 0)) )
|
|
{
|
|
if (cur != firstEntry)
|
|
{
|
|
/* Move to begin */
|
|
if (cur->next)
|
|
cur->next->prev = cur->prev;
|
|
else
|
|
lastEntry = cur->prev;
|
|
cur->prev->next = cur->next;
|
|
cur->prev = NULL;
|
|
firstEntry->prev = cur;
|
|
cur->next = firstEntry;
|
|
firstEntry = cur;
|
|
|
|
#ifdef DEBUG_PROXY_POOL
|
|
CheckLinks();
|
|
#endif
|
|
}
|
|
|
|
cur->refCount ++;
|
|
return cur;
|
|
}
|
|
|
|
if (cur->refCount == 0)
|
|
lastEntryWithZeroRefCount = cur;
|
|
|
|
cur = next;
|
|
}
|
|
|
|
if (currentSize == maxSize)
|
|
{
|
|
if (lastEntryWithZeroRefCount == NULL)
|
|
{
|
|
CPLError(CE_Failure, CPLE_AppDefined,
|
|
"Too many threads are running for the current value of the dataset pool size (%d).\n"
|
|
"or too many proxy datasets are opened in a cascaded way.\n"
|
|
"Try increasing GDAL_MAX_DATASET_POOL_SIZE.", maxSize);
|
|
return NULL;
|
|
}
|
|
|
|
CPLFree(lastEntryWithZeroRefCount->pszFileName);
|
|
lastEntryWithZeroRefCount->pszFileName = NULL;
|
|
if (lastEntryWithZeroRefCount->poDS)
|
|
{
|
|
/* Close by pretending we are the thread that GDALOpen'ed this */
|
|
/* dataset */
|
|
GDALSetResponsiblePIDForCurrentThread(lastEntryWithZeroRefCount->responsiblePID);
|
|
|
|
refCountOfDisableRefCount ++;
|
|
GDALClose(lastEntryWithZeroRefCount->poDS);
|
|
refCountOfDisableRefCount --;
|
|
|
|
lastEntryWithZeroRefCount->poDS = NULL;
|
|
GDALSetResponsiblePIDForCurrentThread(responsiblePID);
|
|
}
|
|
|
|
/* Recycle this entry for the to-be-openeded dataset and */
|
|
/* moves it to the top of the list */
|
|
if (lastEntryWithZeroRefCount->prev)
|
|
lastEntryWithZeroRefCount->prev->next = lastEntryWithZeroRefCount->next;
|
|
else {
|
|
CPLAssert(0);
|
|
}
|
|
if (lastEntryWithZeroRefCount->next)
|
|
lastEntryWithZeroRefCount->next->prev = lastEntryWithZeroRefCount->prev;
|
|
else
|
|
{
|
|
CPLAssert(lastEntryWithZeroRefCount == lastEntry);
|
|
lastEntry->prev->next = NULL;
|
|
lastEntry = lastEntry->prev;
|
|
}
|
|
lastEntryWithZeroRefCount->prev = NULL;
|
|
lastEntryWithZeroRefCount->next = firstEntry;
|
|
firstEntry->prev = lastEntryWithZeroRefCount;
|
|
cur = firstEntry = lastEntryWithZeroRefCount;
|
|
#ifdef DEBUG_PROXY_POOL
|
|
CheckLinks();
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
/* Prepend */
|
|
cur = (GDALProxyPoolCacheEntry*) CPLMalloc(sizeof(GDALProxyPoolCacheEntry));
|
|
if (lastEntry == NULL)
|
|
lastEntry = cur;
|
|
cur->prev = NULL;
|
|
cur->next = firstEntry;
|
|
if (firstEntry)
|
|
firstEntry->prev = cur;
|
|
firstEntry = cur;
|
|
currentSize ++;
|
|
#ifdef DEBUG_PROXY_POOL
|
|
CheckLinks();
|
|
#endif
|
|
}
|
|
|
|
cur->pszFileName = CPLStrdup(pszFileName);
|
|
cur->responsiblePID = responsiblePID;
|
|
cur->refCount = 1;
|
|
|
|
refCountOfDisableRefCount ++;
|
|
int nFlag = ((eAccess == GA_Update) ? GDAL_OF_UPDATE : GDAL_OF_READONLY) | GDAL_OF_RASTER | GDAL_OF_VERBOSE_ERROR;
|
|
cur->poDS = (GDALDataset*) GDALOpenEx( pszFileName, nFlag, NULL,
|
|
(const char* const* )papszOpenOptions, NULL );
|
|
refCountOfDisableRefCount --;
|
|
|
|
return cur;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* _CloseDataset() */
|
|
/************************************************************************/
|
|
|
|
void GDALDatasetPool::_CloseDataset(const char* pszFileName, GDALAccess eAccess)
|
|
{
|
|
GDALProxyPoolCacheEntry* cur = firstEntry;
|
|
GIntBig responsiblePID = GDALGetResponsiblePIDForCurrentThread();
|
|
|
|
while(cur)
|
|
{
|
|
GDALProxyPoolCacheEntry* next = cur->next;
|
|
|
|
if (strcmp(cur->pszFileName, pszFileName) == 0 && cur->refCount == 0 &&
|
|
cur->poDS != NULL )
|
|
{
|
|
/* Close by pretending we are the thread that GDALOpen'ed this */
|
|
/* dataset */
|
|
GDALSetResponsiblePIDForCurrentThread(cur->responsiblePID);
|
|
|
|
refCountOfDisableRefCount ++;
|
|
GDALClose(cur->poDS);
|
|
refCountOfDisableRefCount --;
|
|
|
|
GDALSetResponsiblePIDForCurrentThread(responsiblePID);
|
|
|
|
cur->poDS = NULL;
|
|
cur->pszFileName[0] = '\0';
|
|
break;
|
|
}
|
|
|
|
cur = next;
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Ref() */
|
|
/************************************************************************/
|
|
|
|
void GDALDatasetPool::Ref()
|
|
{
|
|
CPLMutexHolderD( GDALGetphDLMutex() );
|
|
if (singleton == NULL)
|
|
{
|
|
int maxSize = atoi(CPLGetConfigOption("GDAL_MAX_DATASET_POOL_SIZE", "100"));
|
|
if (maxSize < 2 || maxSize > 1000)
|
|
maxSize = 100;
|
|
singleton = new GDALDatasetPool(maxSize);
|
|
}
|
|
if (singleton->refCountOfDisableRefCount == 0)
|
|
singleton->refCount++;
|
|
}
|
|
|
|
/* keep that in sync with gdaldrivermanager.cpp */
|
|
void GDALDatasetPool::PreventDestroy()
|
|
{
|
|
CPLMutexHolderD( GDALGetphDLMutex() );
|
|
if (! singleton)
|
|
return;
|
|
singleton->refCountOfDisableRefCount ++;
|
|
}
|
|
|
|
/* keep that in sync with gdaldrivermanager.cpp */
|
|
void GDALDatasetPoolPreventDestroy()
|
|
{
|
|
GDALDatasetPool::PreventDestroy();
|
|
}
|
|
|
|
|
|
/************************************************************************/
|
|
/* Unref() */
|
|
/************************************************************************/
|
|
|
|
void GDALDatasetPool::Unref()
|
|
{
|
|
CPLMutexHolderD( GDALGetphDLMutex() );
|
|
if (! singleton)
|
|
{
|
|
CPLAssert(0);
|
|
return;
|
|
}
|
|
if (singleton->refCountOfDisableRefCount == 0)
|
|
{
|
|
singleton->refCount--;
|
|
if (singleton->refCount == 0)
|
|
{
|
|
delete singleton;
|
|
singleton = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* keep that in sync with gdaldrivermanager.cpp */
|
|
void GDALDatasetPool::ForceDestroy()
|
|
{
|
|
CPLMutexHolderD( GDALGetphDLMutex() );
|
|
if (! singleton)
|
|
return;
|
|
singleton->refCountOfDisableRefCount --;
|
|
CPLAssert(singleton->refCountOfDisableRefCount == 0);
|
|
singleton->refCount = 0;
|
|
delete singleton;
|
|
singleton = NULL;
|
|
}
|
|
|
|
/* keep that in sync with gdaldrivermanager.cpp */
|
|
void GDALDatasetPoolForceDestroy()
|
|
{
|
|
GDALDatasetPool::ForceDestroy();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* RefDataset() */
|
|
/************************************************************************/
|
|
|
|
GDALProxyPoolCacheEntry* GDALDatasetPool::RefDataset(const char* pszFileName,
|
|
GDALAccess eAccess,
|
|
char** papszOpenOptions,
|
|
int bShared)
|
|
{
|
|
CPLMutexHolderD( GDALGetphDLMutex() );
|
|
return singleton->_RefDataset(pszFileName, eAccess, papszOpenOptions, bShared);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* UnrefDataset() */
|
|
/************************************************************************/
|
|
|
|
void GDALDatasetPool::UnrefDataset(GDALProxyPoolCacheEntry* cacheEntry)
|
|
{
|
|
CPLMutexHolderD( GDALGetphDLMutex() );
|
|
cacheEntry->refCount --;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* CloseDataset() */
|
|
/************************************************************************/
|
|
|
|
void GDALDatasetPool::CloseDataset(const char* pszFileName, GDALAccess eAccess)
|
|
{
|
|
CPLMutexHolderD( GDALGetphDLMutex() );
|
|
singleton->_CloseDataset(pszFileName, eAccess);
|
|
}
|
|
|
|
CPL_C_START
|
|
|
|
typedef struct
|
|
{
|
|
char* pszDomain;
|
|
char** papszMetadata;
|
|
} GetMetadataElt;
|
|
|
|
static
|
|
unsigned long hash_func_get_metadata(const void* _elt)
|
|
{
|
|
GetMetadataElt* elt = (GetMetadataElt*) _elt;
|
|
return CPLHashSetHashStr(elt->pszDomain);
|
|
}
|
|
|
|
static
|
|
int equal_func_get_metadata(const void* _elt1, const void* _elt2)
|
|
{
|
|
GetMetadataElt* elt1 = (GetMetadataElt*) _elt1;
|
|
GetMetadataElt* elt2 = (GetMetadataElt*) _elt2;
|
|
return CPLHashSetEqualStr(elt1->pszDomain, elt2->pszDomain);
|
|
}
|
|
|
|
static
|
|
void free_func_get_metadata(void* _elt)
|
|
{
|
|
GetMetadataElt* elt = (GetMetadataElt*) _elt;
|
|
CPLFree(elt->pszDomain);
|
|
CSLDestroy(elt->papszMetadata);
|
|
}
|
|
|
|
|
|
typedef struct
|
|
{
|
|
char* pszName;
|
|
char* pszDomain;
|
|
char* pszMetadataItem;
|
|
} GetMetadataItemElt;
|
|
|
|
static
|
|
unsigned long hash_func_get_metadata_item(const void* _elt)
|
|
{
|
|
GetMetadataItemElt* elt = (GetMetadataItemElt*) _elt;
|
|
return CPLHashSetHashStr(elt->pszName) ^ CPLHashSetHashStr(elt->pszDomain);
|
|
}
|
|
|
|
static
|
|
int equal_func_get_metadata_item(const void* _elt1, const void* _elt2)
|
|
{
|
|
GetMetadataItemElt* elt1 = (GetMetadataItemElt*) _elt1;
|
|
GetMetadataItemElt* elt2 = (GetMetadataItemElt*) _elt2;
|
|
return CPLHashSetEqualStr(elt1->pszName, elt2->pszName) &&
|
|
CPLHashSetEqualStr(elt1->pszDomain, elt2->pszDomain);
|
|
}
|
|
|
|
static
|
|
void free_func_get_metadata_item(void* _elt)
|
|
{
|
|
GetMetadataItemElt* elt = (GetMetadataItemElt*) _elt;
|
|
CPLFree(elt->pszName);
|
|
CPLFree(elt->pszDomain);
|
|
CPLFree(elt->pszMetadataItem);
|
|
}
|
|
|
|
CPL_C_END
|
|
|
|
/* ******************************************************************** */
|
|
/* GDALProxyPoolDataset */
|
|
/* ******************************************************************** */
|
|
|
|
/* Note : the bShared parameter must be used with caution. You can */
|
|
/* set it to TRUE for being used as a VRT source : in that case, */
|
|
/* VRTSimpleSource will take care of destroying it when there are no */
|
|
/* reference to it (in VRTSimpleSource::~VRTSimpleSource()) */
|
|
/* However this will not be registered as a genuine shared dataset, like it */
|
|
/* would have been with MarkAsShared(). But MarkAsShared() is not usable for */
|
|
/* GDALProxyPoolDataset objects, as they share the same description as their */
|
|
/* underlying dataset. So *NEVER* call MarkAsShared() on a GDALProxyPoolDataset */
|
|
/* object */
|
|
|
|
GDALProxyPoolDataset::GDALProxyPoolDataset(const char* pszSourceDatasetDescription,
|
|
int nRasterXSize, int nRasterYSize,
|
|
GDALAccess eAccess, int bShared,
|
|
const char * pszProjectionRef,
|
|
double * padfGeoTransform)
|
|
{
|
|
GDALDatasetPool::Ref();
|
|
|
|
SetDescription(pszSourceDatasetDescription);
|
|
|
|
this->nRasterXSize = nRasterXSize;
|
|
this->nRasterYSize = nRasterYSize;
|
|
this->eAccess = eAccess;
|
|
|
|
this->bShared = bShared;
|
|
|
|
this->responsiblePID = GDALGetResponsiblePIDForCurrentThread();
|
|
|
|
if (pszProjectionRef)
|
|
{
|
|
this->pszProjectionRef = NULL;
|
|
bHasSrcProjection = FALSE;
|
|
}
|
|
else
|
|
{
|
|
this->pszProjectionRef = CPLStrdup(pszProjectionRef);
|
|
bHasSrcProjection = TRUE;
|
|
}
|
|
if (padfGeoTransform)
|
|
{
|
|
memcpy(adfGeoTransform, padfGeoTransform,6 * sizeof(double));
|
|
bHasSrcGeoTransform = TRUE;
|
|
}
|
|
else
|
|
{
|
|
adfGeoTransform[0] = 0;
|
|
adfGeoTransform[1] = 1;
|
|
adfGeoTransform[2] = 0;
|
|
adfGeoTransform[3] = 0;
|
|
adfGeoTransform[4] = 0;
|
|
adfGeoTransform[5] = 1;
|
|
bHasSrcGeoTransform = FALSE;
|
|
}
|
|
|
|
pszGCPProjection = NULL;
|
|
nGCPCount = 0;
|
|
pasGCPList = NULL;
|
|
metadataSet = NULL;
|
|
metadataItemSet = NULL;
|
|
cacheEntry = NULL;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* ~GDALProxyPoolDataset() */
|
|
/************************************************************************/
|
|
|
|
GDALProxyPoolDataset::~GDALProxyPoolDataset()
|
|
{
|
|
if( !bShared )
|
|
{
|
|
GDALDatasetPool::CloseDataset(GetDescription(), eAccess);
|
|
}
|
|
/* See comment in constructor */
|
|
/* It is not really a genuine shared dataset, so we don't */
|
|
/* want ~GDALDataset() to try to release it from its */
|
|
/* shared dataset hashset. This will save a */
|
|
/* "Should not happen. Cannot find %s, this=%p in phSharedDatasetSet" debug message */
|
|
bShared = FALSE;
|
|
|
|
CPLFree(pszProjectionRef);
|
|
CPLFree(pszGCPProjection);
|
|
if (nGCPCount)
|
|
{
|
|
GDALDeinitGCPs( nGCPCount, pasGCPList );
|
|
CPLFree( pasGCPList );
|
|
}
|
|
if (metadataSet)
|
|
CPLHashSetDestroy(metadataSet);
|
|
if (metadataItemSet)
|
|
CPLHashSetDestroy(metadataItemSet);
|
|
|
|
GDALDatasetPool::Unref();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* SetOpenOptions() */
|
|
/************************************************************************/
|
|
|
|
void GDALProxyPoolDataset::SetOpenOptions(char** papszOpenOptions)
|
|
{
|
|
CPLAssert(this->papszOpenOptions == NULL);
|
|
this->papszOpenOptions = CSLDuplicate(papszOpenOptions);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* AddSrcBandDescription() */
|
|
/************************************************************************/
|
|
|
|
void GDALProxyPoolDataset::AddSrcBandDescription( GDALDataType eDataType, int nBlockXSize, int nBlockYSize)
|
|
{
|
|
SetBand(nBands + 1, new GDALProxyPoolRasterBand(this, nBands + 1, eDataType, nBlockXSize, nBlockYSize));
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* RefUnderlyingDataset() */
|
|
/************************************************************************/
|
|
|
|
GDALDataset* GDALProxyPoolDataset::RefUnderlyingDataset()
|
|
{
|
|
/* We pretend that the current thread is responsiblePID, that is */
|
|
/* to say the thread that created that GDALProxyPoolDataset object. */
|
|
/* This is for the case when a GDALProxyPoolDataset is created by a */
|
|
/* thread and used by other threads. These other threads, when doing actual */
|
|
/* IO, will come there and potentially open the underlying dataset. */
|
|
/* By doing this, they can indirectly call GDALOpenShared() on .aux file */
|
|
/* for example. So this call to GDALOpenShared() must occur as if it */
|
|
/* was done by the creating thread, otherwise it will not be correctly closed afterwards... */
|
|
/* To make a long story short : this is necessary when warping with ChunkAndWarpMulti */
|
|
/* a VRT of GeoTIFFs that have associated .aux files */
|
|
GIntBig curResponsiblePID = GDALGetResponsiblePIDForCurrentThread();
|
|
GDALSetResponsiblePIDForCurrentThread(responsiblePID);
|
|
cacheEntry = GDALDatasetPool::RefDataset(GetDescription(), eAccess, papszOpenOptions,
|
|
GetShared());
|
|
GDALSetResponsiblePIDForCurrentThread(curResponsiblePID);
|
|
if (cacheEntry != NULL)
|
|
{
|
|
if (cacheEntry->poDS != NULL)
|
|
return cacheEntry->poDS;
|
|
else
|
|
GDALDatasetPool::UnrefDataset(cacheEntry);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* UnrefUnderlyingDataset() */
|
|
/************************************************************************/
|
|
|
|
void GDALProxyPoolDataset::UnrefUnderlyingDataset(CPL_UNUSED GDALDataset* poUnderlyingDataset)
|
|
{
|
|
if (cacheEntry != NULL)
|
|
{
|
|
CPLAssert(cacheEntry->poDS == poUnderlyingDataset);
|
|
if (cacheEntry->poDS != NULL)
|
|
GDALDatasetPool::UnrefDataset(cacheEntry);
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* SetProjection() */
|
|
/************************************************************************/
|
|
|
|
CPLErr GDALProxyPoolDataset::SetProjection(const char* pszProjectionRef)
|
|
{
|
|
bHasSrcProjection = FALSE;
|
|
return GDALProxyDataset::SetProjection(pszProjectionRef);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetProjectionRef() */
|
|
/************************************************************************/
|
|
|
|
const char *GDALProxyPoolDataset::GetProjectionRef()
|
|
{
|
|
if (bHasSrcProjection)
|
|
return pszProjectionRef;
|
|
else
|
|
return GDALProxyDataset::GetProjectionRef();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* SetGeoTransform() */
|
|
/************************************************************************/
|
|
|
|
CPLErr GDALProxyPoolDataset::SetGeoTransform( double * padfGeoTransform )
|
|
{
|
|
bHasSrcGeoTransform = FALSE;
|
|
return GDALProxyDataset::SetGeoTransform(padfGeoTransform);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetGeoTransform() */
|
|
/************************************************************************/
|
|
|
|
CPLErr GDALProxyPoolDataset::GetGeoTransform( double * padfGeoTransform )
|
|
{
|
|
if (bHasSrcGeoTransform)
|
|
{
|
|
memcpy(padfGeoTransform, adfGeoTransform, 6 * sizeof(double));
|
|
return CE_None;
|
|
}
|
|
else
|
|
{
|
|
return GDALProxyDataset::GetGeoTransform(padfGeoTransform);
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetMetadata() */
|
|
/************************************************************************/
|
|
|
|
char **GDALProxyPoolDataset::GetMetadata( const char * pszDomain )
|
|
{
|
|
if (metadataSet == NULL)
|
|
metadataSet = CPLHashSetNew(hash_func_get_metadata,
|
|
equal_func_get_metadata,
|
|
free_func_get_metadata);
|
|
|
|
GDALDataset* poUnderlyingDataset = RefUnderlyingDataset();
|
|
if (poUnderlyingDataset == NULL)
|
|
return NULL;
|
|
|
|
char** papszUnderlyingMetadata = poUnderlyingDataset->GetMetadata(pszDomain);
|
|
|
|
GetMetadataElt* pElt = (GetMetadataElt*) CPLMalloc(sizeof(GetMetadataElt));
|
|
pElt->pszDomain = (pszDomain) ? CPLStrdup(pszDomain) : NULL;
|
|
pElt->papszMetadata = CSLDuplicate(papszUnderlyingMetadata);
|
|
CPLHashSetInsert(metadataSet, pElt);
|
|
|
|
UnrefUnderlyingDataset(poUnderlyingDataset);
|
|
|
|
return pElt->papszMetadata;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetMetadataItem() */
|
|
/************************************************************************/
|
|
|
|
const char *GDALProxyPoolDataset::GetMetadataItem( const char * pszName,
|
|
const char * pszDomain )
|
|
{
|
|
if (metadataItemSet == NULL)
|
|
metadataItemSet = CPLHashSetNew(hash_func_get_metadata_item,
|
|
equal_func_get_metadata_item,
|
|
free_func_get_metadata_item);
|
|
|
|
GDALDataset* poUnderlyingDataset = RefUnderlyingDataset();
|
|
if (poUnderlyingDataset == NULL)
|
|
return NULL;
|
|
|
|
const char* pszUnderlyingMetadataItem =
|
|
poUnderlyingDataset->GetMetadataItem(pszName, pszDomain);
|
|
|
|
GetMetadataItemElt* pElt = (GetMetadataItemElt*) CPLMalloc(sizeof(GetMetadataItemElt));
|
|
pElt->pszName = (pszName) ? CPLStrdup(pszName) : NULL;
|
|
pElt->pszDomain = (pszDomain) ? CPLStrdup(pszDomain) : NULL;
|
|
pElt->pszMetadataItem = (pszUnderlyingMetadataItem) ? CPLStrdup(pszUnderlyingMetadataItem) : NULL;
|
|
CPLHashSetInsert(metadataItemSet, pElt);
|
|
|
|
UnrefUnderlyingDataset(poUnderlyingDataset);
|
|
|
|
return pElt->pszMetadataItem;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetInternalHandle() */
|
|
/************************************************************************/
|
|
|
|
void *GDALProxyPoolDataset::GetInternalHandle( const char * pszRequest)
|
|
{
|
|
CPLError(CE_Warning, CPLE_AppDefined,
|
|
"GetInternalHandle() cannot be safely called on a proxy pool dataset\n"
|
|
"as the returned value may be invalidated at any time.\n");
|
|
return GDALProxyDataset::GetInternalHandle(pszRequest);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetGCPProjection() */
|
|
/************************************************************************/
|
|
|
|
const char *GDALProxyPoolDataset::GetGCPProjection()
|
|
{
|
|
GDALDataset* poUnderlyingDataset = RefUnderlyingDataset();
|
|
if (poUnderlyingDataset == NULL)
|
|
return NULL;
|
|
|
|
CPLFree(pszGCPProjection);
|
|
pszGCPProjection = NULL;
|
|
|
|
const char* pszUnderlyingGCPProjection = poUnderlyingDataset->GetGCPProjection();
|
|
if (pszUnderlyingGCPProjection)
|
|
pszGCPProjection = CPLStrdup(pszUnderlyingGCPProjection);
|
|
|
|
UnrefUnderlyingDataset(poUnderlyingDataset);
|
|
|
|
return pszGCPProjection;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetGCPs() */
|
|
/************************************************************************/
|
|
|
|
const GDAL_GCP *GDALProxyPoolDataset::GetGCPs()
|
|
{
|
|
GDALDataset* poUnderlyingDataset = RefUnderlyingDataset();
|
|
if (poUnderlyingDataset == NULL)
|
|
return NULL;
|
|
|
|
if (nGCPCount)
|
|
{
|
|
GDALDeinitGCPs( nGCPCount, pasGCPList );
|
|
CPLFree( pasGCPList );
|
|
pasGCPList = NULL;
|
|
}
|
|
|
|
const GDAL_GCP* pasUnderlyingGCPList = poUnderlyingDataset->GetGCPs();
|
|
nGCPCount = poUnderlyingDataset->GetGCPCount();
|
|
if (nGCPCount)
|
|
pasGCPList = GDALDuplicateGCPs(nGCPCount, pasUnderlyingGCPList );
|
|
|
|
UnrefUnderlyingDataset(poUnderlyingDataset);
|
|
|
|
return pasGCPList;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALProxyPoolDatasetCreate() */
|
|
/************************************************************************/
|
|
|
|
GDALProxyPoolDatasetH GDALProxyPoolDatasetCreate(const char* pszSourceDatasetDescription,
|
|
int nRasterXSize, int nRasterYSize,
|
|
GDALAccess eAccess, int bShared,
|
|
const char * pszProjectionRef,
|
|
double * padfGeoTransform)
|
|
{
|
|
return (GDALProxyPoolDatasetH)
|
|
new GDALProxyPoolDataset(pszSourceDatasetDescription,
|
|
nRasterXSize, nRasterYSize,
|
|
eAccess, bShared,
|
|
pszProjectionRef, padfGeoTransform);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALProxyPoolDatasetDelete() */
|
|
/************************************************************************/
|
|
|
|
void CPL_DLL GDALProxyPoolDatasetDelete(GDALProxyPoolDatasetH hProxyPoolDataset)
|
|
{
|
|
delete (GDALProxyPoolDataset*)hProxyPoolDataset;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GDALProxyPoolDatasetAddSrcBandDescription() */
|
|
/************************************************************************/
|
|
|
|
void GDALProxyPoolDatasetAddSrcBandDescription( GDALProxyPoolDatasetH hProxyPoolDataset,
|
|
GDALDataType eDataType,
|
|
int nBlockXSize, int nBlockYSize)
|
|
{
|
|
((GDALProxyPoolDataset*)hProxyPoolDataset)->
|
|
AddSrcBandDescription(eDataType, nBlockXSize, nBlockYSize);
|
|
}
|
|
|
|
/* ******************************************************************** */
|
|
/* GDALProxyPoolRasterBand() */
|
|
/* ******************************************************************** */
|
|
|
|
GDALProxyPoolRasterBand::GDALProxyPoolRasterBand(GDALProxyPoolDataset* poDS, int nBand,
|
|
GDALDataType eDataType,
|
|
int nBlockXSize, int nBlockYSize)
|
|
{
|
|
this->poDS = poDS;
|
|
this->nBand = nBand;
|
|
this->eDataType = eDataType;
|
|
this->nRasterXSize = poDS->GetRasterXSize();
|
|
this->nRasterYSize = poDS->GetRasterYSize();
|
|
this->nBlockXSize = nBlockXSize;
|
|
this->nBlockYSize = nBlockYSize;
|
|
|
|
Init();
|
|
}
|
|
|
|
/* ******************************************************************** */
|
|
/* GDALProxyPoolRasterBand() */
|
|
/* ******************************************************************** */
|
|
|
|
GDALProxyPoolRasterBand::GDALProxyPoolRasterBand(GDALProxyPoolDataset* poDS,
|
|
GDALRasterBand* poUnderlyingRasterBand)
|
|
{
|
|
this->poDS = poDS;
|
|
this->nBand = poUnderlyingRasterBand->GetBand();
|
|
this->eDataType = poUnderlyingRasterBand->GetRasterDataType();
|
|
this->nRasterXSize = poUnderlyingRasterBand->GetXSize();
|
|
this->nRasterYSize = poUnderlyingRasterBand->GetYSize();
|
|
poUnderlyingRasterBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
|
|
|
|
Init();
|
|
}
|
|
|
|
/* ******************************************************************** */
|
|
/* Init() */
|
|
/* ******************************************************************** */
|
|
|
|
void GDALProxyPoolRasterBand::Init()
|
|
{
|
|
metadataSet = NULL;
|
|
metadataItemSet = NULL;
|
|
pszUnitType = NULL;
|
|
papszCategoryNames = NULL;
|
|
poColorTable = NULL;
|
|
|
|
nSizeProxyOverviewRasterBand = 0;
|
|
papoProxyOverviewRasterBand = NULL;
|
|
poProxyMaskBand = NULL;
|
|
}
|
|
|
|
/* ******************************************************************** */
|
|
/* ~GDALProxyPoolRasterBand() */
|
|
/* ******************************************************************** */
|
|
GDALProxyPoolRasterBand::~GDALProxyPoolRasterBand()
|
|
{
|
|
if (metadataSet)
|
|
CPLHashSetDestroy(metadataSet);
|
|
if (metadataItemSet)
|
|
CPLHashSetDestroy(metadataItemSet);
|
|
CPLFree(pszUnitType);
|
|
CSLDestroy(papszCategoryNames);
|
|
if (poColorTable)
|
|
delete poColorTable;
|
|
|
|
int i;
|
|
for(i=0;i<nSizeProxyOverviewRasterBand;i++)
|
|
{
|
|
if (papoProxyOverviewRasterBand[i])
|
|
delete papoProxyOverviewRasterBand[i];
|
|
}
|
|
CPLFree(papoProxyOverviewRasterBand);
|
|
if (poProxyMaskBand)
|
|
delete poProxyMaskBand;
|
|
}
|
|
|
|
|
|
/************************************************************************/
|
|
/* AddSrcMaskBandDescription() */
|
|
/************************************************************************/
|
|
|
|
void GDALProxyPoolRasterBand::AddSrcMaskBandDescription( GDALDataType eDataType,
|
|
int nBlockXSize,
|
|
int nBlockYSize)
|
|
{
|
|
CPLAssert(poProxyMaskBand == NULL);
|
|
poProxyMaskBand = new GDALProxyPoolMaskBand((GDALProxyPoolDataset*)poDS,
|
|
this, eDataType,
|
|
nBlockXSize, nBlockYSize);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* RefUnderlyingRasterBand() */
|
|
/************************************************************************/
|
|
|
|
GDALRasterBand* GDALProxyPoolRasterBand::RefUnderlyingRasterBand()
|
|
{
|
|
GDALDataset* poUnderlyingDataset = ((GDALProxyPoolDataset*)poDS)->RefUnderlyingDataset();
|
|
if (poUnderlyingDataset == NULL)
|
|
return NULL;
|
|
|
|
GDALRasterBand* poBand = poUnderlyingDataset->GetRasterBand(nBand);
|
|
if (poBand == NULL)
|
|
{
|
|
((GDALProxyPoolDataset*)poDS)->UnrefUnderlyingDataset(poUnderlyingDataset);
|
|
}
|
|
|
|
return poBand;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* UnrefUnderlyingRasterBand() */
|
|
/************************************************************************/
|
|
|
|
void GDALProxyPoolRasterBand::UnrefUnderlyingRasterBand(GDALRasterBand* poUnderlyingRasterBand)
|
|
{
|
|
if (poUnderlyingRasterBand)
|
|
((GDALProxyPoolDataset*)poDS)->UnrefUnderlyingDataset(poUnderlyingRasterBand->GetDataset());
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetMetadata() */
|
|
/************************************************************************/
|
|
|
|
char **GDALProxyPoolRasterBand::GetMetadata( const char * pszDomain )
|
|
{
|
|
if (metadataSet == NULL)
|
|
metadataSet = CPLHashSetNew(hash_func_get_metadata,
|
|
equal_func_get_metadata,
|
|
free_func_get_metadata);
|
|
|
|
GDALRasterBand* poUnderlyingRasterBand = RefUnderlyingRasterBand();
|
|
if (poUnderlyingRasterBand == NULL)
|
|
return NULL;
|
|
|
|
char** papszUnderlyingMetadata = poUnderlyingRasterBand->GetMetadata(pszDomain);
|
|
|
|
GetMetadataElt* pElt = (GetMetadataElt*) CPLMalloc(sizeof(GetMetadataElt));
|
|
pElt->pszDomain = (pszDomain) ? CPLStrdup(pszDomain) : NULL;
|
|
pElt->papszMetadata = CSLDuplicate(papszUnderlyingMetadata);
|
|
CPLHashSetInsert(metadataSet, pElt);
|
|
|
|
UnrefUnderlyingRasterBand(poUnderlyingRasterBand);
|
|
|
|
return pElt->papszMetadata;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* GetMetadataItem() */
|
|
/************************************************************************/
|
|
|
|
const char *GDALProxyPoolRasterBand::GetMetadataItem( const char * pszName,
|
|
const char * pszDomain )
|
|
{
|
|
if (metadataItemSet == NULL)
|
|
metadataItemSet = CPLHashSetNew(hash_func_get_metadata_item,
|
|
equal_func_get_metadata_item,
|
|
free_func_get_metadata_item);
|
|
|
|
GDALRasterBand* poUnderlyingRasterBand = RefUnderlyingRasterBand();
|
|
if (poUnderlyingRasterBand == NULL)
|
|
return NULL;
|
|
|
|
const char* pszUnderlyingMetadataItem =
|
|
poUnderlyingRasterBand->GetMetadataItem(pszName, pszDomain);
|
|
|
|
GetMetadataItemElt* pElt = (GetMetadataItemElt*) CPLMalloc(sizeof(GetMetadataItemElt));
|
|
pElt->pszName = (pszName) ? CPLStrdup(pszName) : NULL;
|
|
pElt->pszDomain = (pszDomain) ? CPLStrdup(pszDomain) : NULL;
|
|
pElt->pszMetadataItem = (pszUnderlyingMetadataItem) ? CPLStrdup(pszUnderlyingMetadataItem) : NULL;
|
|
CPLHashSetInsert(metadataItemSet, pElt);
|
|
|
|
UnrefUnderlyingRasterBand(poUnderlyingRasterBand);
|
|
|
|
return pElt->pszMetadataItem;
|
|
}
|
|
|
|
/* ******************************************************************** */
|
|
/* GetCategoryNames() */
|
|
/* ******************************************************************** */
|
|
|
|
char **GDALProxyPoolRasterBand::GetCategoryNames()
|
|
{
|
|
GDALRasterBand* poUnderlyingRasterBand = RefUnderlyingRasterBand();
|
|
if (poUnderlyingRasterBand == NULL)
|
|
return NULL;
|
|
|
|
CSLDestroy(papszCategoryNames);
|
|
papszCategoryNames = NULL;
|
|
|
|
char** papszUnderlyingCategoryNames = poUnderlyingRasterBand->GetCategoryNames();
|
|
if (papszUnderlyingCategoryNames)
|
|
papszCategoryNames = CSLDuplicate(papszUnderlyingCategoryNames);
|
|
|
|
UnrefUnderlyingRasterBand(poUnderlyingRasterBand);
|
|
|
|
return papszCategoryNames;
|
|
}
|
|
|
|
/* ******************************************************************** */
|
|
/* GetUnitType() */
|
|
/* ******************************************************************** */
|
|
|
|
const char *GDALProxyPoolRasterBand::GetUnitType()
|
|
{
|
|
GDALRasterBand* poUnderlyingRasterBand = RefUnderlyingRasterBand();
|
|
if (poUnderlyingRasterBand == NULL)
|
|
return NULL;
|
|
|
|
CPLFree(pszUnitType);
|
|
pszUnitType = NULL;
|
|
|
|
const char* pszUnderlyingUnitType = poUnderlyingRasterBand->GetUnitType();
|
|
if (pszUnderlyingUnitType)
|
|
pszUnitType = CPLStrdup(pszUnderlyingUnitType);
|
|
|
|
UnrefUnderlyingRasterBand(poUnderlyingRasterBand);
|
|
|
|
return pszUnitType;
|
|
}
|
|
|
|
/* ******************************************************************** */
|
|
/* GetColorTable() */
|
|
/* ******************************************************************** */
|
|
|
|
GDALColorTable *GDALProxyPoolRasterBand::GetColorTable()
|
|
{
|
|
GDALRasterBand* poUnderlyingRasterBand = RefUnderlyingRasterBand();
|
|
if (poUnderlyingRasterBand == NULL)
|
|
return NULL;
|
|
|
|
if (poColorTable)
|
|
delete poColorTable;
|
|
poColorTable = NULL;
|
|
|
|
GDALColorTable* poUnderlyingColorTable = poUnderlyingRasterBand->GetColorTable();
|
|
if (poUnderlyingColorTable)
|
|
poColorTable = poUnderlyingColorTable->Clone();
|
|
|
|
UnrefUnderlyingRasterBand(poUnderlyingRasterBand);
|
|
|
|
return poColorTable;
|
|
}
|
|
|
|
/* ******************************************************************** */
|
|
/* GetOverview() */
|
|
/* ******************************************************************** */
|
|
|
|
GDALRasterBand *GDALProxyPoolRasterBand::GetOverview(int nOverviewBand)
|
|
{
|
|
if (nOverviewBand >= 0 && nOverviewBand < nSizeProxyOverviewRasterBand)
|
|
{
|
|
if (papoProxyOverviewRasterBand[nOverviewBand])
|
|
return papoProxyOverviewRasterBand[nOverviewBand];
|
|
}
|
|
|
|
GDALRasterBand* poUnderlyingRasterBand = RefUnderlyingRasterBand();
|
|
if (poUnderlyingRasterBand == NULL)
|
|
return NULL;
|
|
|
|
GDALRasterBand* poOverviewRasterBand = poUnderlyingRasterBand->GetOverview(nOverviewBand);
|
|
if (poOverviewRasterBand == NULL)
|
|
{
|
|
UnrefUnderlyingRasterBand(poUnderlyingRasterBand);
|
|
return NULL;
|
|
}
|
|
|
|
if (nOverviewBand >= nSizeProxyOverviewRasterBand)
|
|
{
|
|
int i;
|
|
papoProxyOverviewRasterBand = (GDALProxyPoolOverviewRasterBand**)
|
|
CPLRealloc(papoProxyOverviewRasterBand,
|
|
sizeof(GDALProxyPoolOverviewRasterBand*) * (nOverviewBand + 1));
|
|
for(i=nSizeProxyOverviewRasterBand; i<nOverviewBand + 1;i++)
|
|
papoProxyOverviewRasterBand[i] = NULL;
|
|
nSizeProxyOverviewRasterBand = nOverviewBand + 1;
|
|
}
|
|
|
|
papoProxyOverviewRasterBand[nOverviewBand] =
|
|
new GDALProxyPoolOverviewRasterBand((GDALProxyPoolDataset*)poDS,
|
|
poOverviewRasterBand,
|
|
this, nOverviewBand);
|
|
|
|
UnrefUnderlyingRasterBand(poUnderlyingRasterBand);
|
|
|
|
return papoProxyOverviewRasterBand[nOverviewBand];
|
|
}
|
|
|
|
/* ******************************************************************** */
|
|
/* GetRasterSampleOverview() */
|
|
/* ******************************************************************** */
|
|
|
|
GDALRasterBand *GDALProxyPoolRasterBand::GetRasterSampleOverview( CPL_UNUSED GUIntBig nDesiredSamples)
|
|
{
|
|
CPLError(CE_Failure, CPLE_AppDefined,
|
|
"GDALProxyPoolRasterBand::GetRasterSampleOverview : not implemented yet");
|
|
return NULL;
|
|
}
|
|
|
|
/* ******************************************************************** */
|
|
/* GetMaskBand() */
|
|
/* ******************************************************************** */
|
|
|
|
GDALRasterBand *GDALProxyPoolRasterBand::GetMaskBand()
|
|
{
|
|
if (poProxyMaskBand)
|
|
return poProxyMaskBand;
|
|
|
|
GDALRasterBand* poUnderlyingRasterBand = RefUnderlyingRasterBand();
|
|
if (poUnderlyingRasterBand == NULL)
|
|
return NULL;
|
|
|
|
GDALRasterBand* poMaskBand = poUnderlyingRasterBand->GetMaskBand();
|
|
|
|
poProxyMaskBand =
|
|
new GDALProxyPoolMaskBand((GDALProxyPoolDataset*)poDS,
|
|
poMaskBand,
|
|
this);
|
|
|
|
UnrefUnderlyingRasterBand(poUnderlyingRasterBand);
|
|
|
|
return poProxyMaskBand;
|
|
}
|
|
|
|
/* ******************************************************************** */
|
|
/* GDALProxyPoolOverviewRasterBand() */
|
|
/* ******************************************************************** */
|
|
|
|
GDALProxyPoolOverviewRasterBand::GDALProxyPoolOverviewRasterBand(GDALProxyPoolDataset* poDS,
|
|
GDALRasterBand* poUnderlyingOverviewBand,
|
|
GDALProxyPoolRasterBand* poMainBand,
|
|
int nOverviewBand) :
|
|
GDALProxyPoolRasterBand(poDS, poUnderlyingOverviewBand)
|
|
{
|
|
this->poMainBand = poMainBand;
|
|
this->nOverviewBand = nOverviewBand;
|
|
|
|
poUnderlyingMainRasterBand = NULL;
|
|
nRefCountUnderlyingMainRasterBand = 0;
|
|
}
|
|
|
|
/* ******************************************************************** */
|
|
/* ~GDALProxyPoolOverviewRasterBand() */
|
|
/* ******************************************************************** */
|
|
|
|
GDALProxyPoolOverviewRasterBand::~GDALProxyPoolOverviewRasterBand()
|
|
{
|
|
CPLAssert(nRefCountUnderlyingMainRasterBand == 0);
|
|
}
|
|
|
|
/* ******************************************************************** */
|
|
/* RefUnderlyingRasterBand() */
|
|
/* ******************************************************************** */
|
|
|
|
GDALRasterBand* GDALProxyPoolOverviewRasterBand::RefUnderlyingRasterBand()
|
|
{
|
|
poUnderlyingMainRasterBand = poMainBand->RefUnderlyingRasterBand();
|
|
if (poUnderlyingMainRasterBand == NULL)
|
|
return NULL;
|
|
|
|
nRefCountUnderlyingMainRasterBand ++;
|
|
return poUnderlyingMainRasterBand->GetOverview(nOverviewBand);
|
|
}
|
|
|
|
/* ******************************************************************** */
|
|
/* UnrefUnderlyingRasterBand() */
|
|
/* ******************************************************************** */
|
|
|
|
void GDALProxyPoolOverviewRasterBand::UnrefUnderlyingRasterBand(CPL_UNUSED GDALRasterBand* poUnderlyingRasterBand)
|
|
{
|
|
poMainBand->UnrefUnderlyingRasterBand(poUnderlyingMainRasterBand);
|
|
nRefCountUnderlyingMainRasterBand --;
|
|
}
|
|
|
|
|
|
/* ******************************************************************** */
|
|
/* GDALProxyPoolMaskBand() */
|
|
/* ******************************************************************** */
|
|
|
|
GDALProxyPoolMaskBand::GDALProxyPoolMaskBand(GDALProxyPoolDataset* poDS,
|
|
GDALRasterBand* poUnderlyingMaskBand,
|
|
GDALProxyPoolRasterBand* poMainBand) :
|
|
GDALProxyPoolRasterBand(poDS, poUnderlyingMaskBand)
|
|
{
|
|
this->poMainBand = poMainBand;
|
|
|
|
poUnderlyingMainRasterBand = NULL;
|
|
nRefCountUnderlyingMainRasterBand = 0;
|
|
}
|
|
|
|
/* ******************************************************************** */
|
|
/* GDALProxyPoolMaskBand() */
|
|
/* ******************************************************************** */
|
|
|
|
GDALProxyPoolMaskBand::GDALProxyPoolMaskBand(GDALProxyPoolDataset* poDS,
|
|
GDALProxyPoolRasterBand* poMainBand,
|
|
GDALDataType eDataType,
|
|
int nBlockXSize, int nBlockYSize) :
|
|
GDALProxyPoolRasterBand(poDS, 1, eDataType, nBlockXSize, nBlockYSize)
|
|
{
|
|
this->poMainBand = poMainBand;
|
|
|
|
poUnderlyingMainRasterBand = NULL;
|
|
nRefCountUnderlyingMainRasterBand = 0;
|
|
}
|
|
|
|
/* ******************************************************************** */
|
|
/* ~GDALProxyPoolMaskBand() */
|
|
/* ******************************************************************** */
|
|
|
|
GDALProxyPoolMaskBand::~GDALProxyPoolMaskBand()
|
|
{
|
|
CPLAssert(nRefCountUnderlyingMainRasterBand == 0);
|
|
}
|
|
|
|
/* ******************************************************************** */
|
|
/* RefUnderlyingRasterBand() */
|
|
/* ******************************************************************** */
|
|
|
|
GDALRasterBand* GDALProxyPoolMaskBand::RefUnderlyingRasterBand()
|
|
{
|
|
poUnderlyingMainRasterBand = poMainBand->RefUnderlyingRasterBand();
|
|
if (poUnderlyingMainRasterBand == NULL)
|
|
return NULL;
|
|
|
|
nRefCountUnderlyingMainRasterBand ++;
|
|
return poUnderlyingMainRasterBand->GetMaskBand();
|
|
}
|
|
|
|
/* ******************************************************************** */
|
|
/* UnrefUnderlyingRasterBand() */
|
|
/* ******************************************************************** */
|
|
|
|
void GDALProxyPoolMaskBand::UnrefUnderlyingRasterBand(CPL_UNUSED GDALRasterBand* poUnderlyingRasterBand)
|
|
{
|
|
poMainBand->UnrefUnderlyingRasterBand(poUnderlyingMainRasterBand);
|
|
nRefCountUnderlyingMainRasterBand --;
|
|
}
|