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