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