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