Changeset 14792
- Timestamp:
- 06/30/08 17:04:49 (5 months ago)
- Files:
-
- trunk/gdal/frmts/nitf/rpftocdataset.cpp (modified) (19 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/gdal/frmts/nitf/rpftocdataset.cpp
r14557 r14792 29 29 30 30 #include "gdal_pam.h" 31 #include "gdal_proxy.h" 31 32 #include "rpftoclib.h" 32 33 #include "ogr_spatialref.h" … … 200 201 const RPFTocEntry* entry, int isRGBA); 201 202 }; 202 203 /************************************************************************/204 /* ==================================================================== */205 /* RPFTOCGDALDatasetCache */206 /* ==================================================================== */207 /************************************************************************/208 209 class RPFTOCGDALDatasetCache;210 static RPFTOCGDALDatasetCache* singleton = NULL;211 static int refCount = 0;212 static void* RPFTOCCacheMutex = NULL;213 214 typedef struct215 {216 const char* fileName;217 GDALDataset* ds;218 } CacheEntry;219 220 /* This class is a singleton that maintains a pool of opened datasets */221 /* This is to handle efficiently a potential huge number of NITF tiles */222 /* inside a RPFTOC product */223 /* The cache uses a LRU strategy */224 class RPFTOCGDALDatasetCache225 {226 int size;227 CacheEntry* entries;228 229 RPFTOCGDALDatasetCache(int size)230 {231 this->size = size;232 entries = (CacheEntry*)CPLMalloc(size * sizeof(CacheEntry));233 memset(entries, 0, size * sizeof(CacheEntry));234 235 }236 237 ~RPFTOCGDALDatasetCache()238 {239 int i;240 for(i=0;i<size;i++)241 {242 if (entries[i].ds)243 {244 GDALClose(entries[i].ds);245 }246 }247 CPLFree(entries);248 }249 250 GDALDataset* _GetDataset(const char* fileName)251 {252 int i;253 for(i=0;i<size;i++)254 {255 if (entries[i].fileName == NULL)256 {257 if (i != 0)258 memmove(&entries[1], &entries[0], sizeof(CacheEntry) * i);259 entries[0].fileName = fileName;260 entries[0].ds = (GDALDataset *) GDALOpenShared( fileName, GA_ReadOnly );261 return entries[0].ds;262 }263 /* Optimization here : we can compare the strings by address.... */264 else if (entries[i].fileName == fileName)265 {266 if (i != 0)267 {268 GDALDataset* ds = entries[i].ds;269 memmove(&entries[1], &entries[0], sizeof(CacheEntry) * i);270 entries[0].ds = ds;271 entries[0].fileName = fileName;272 }273 return entries[0].ds;274 }275 }276 GDALClose(entries[size-1].ds);277 memmove(&entries[1], &entries[0], sizeof(CacheEntry) * (size-1));278 entries[0].fileName = fileName;279 entries[0].ds = (GDALDataset *) GDALOpenShared( fileName, GA_ReadOnly );280 return entries[0].ds;281 }282 283 public:284 static void Ref()285 {286 CPLMutexHolderD( &RPFTOCCacheMutex );287 if (singleton == NULL)288 singleton = new RPFTOCGDALDatasetCache(100);289 refCount++;290 }291 292 static void Unref()293 {294 CPLMutexHolderD( &RPFTOCCacheMutex );295 refCount--;296 if (refCount == 0)297 {298 delete singleton;299 singleton = NULL;300 }301 }302 303 static GDALDataset* GetDataset(const char* fileName)304 {305 CPLMutexHolderD( &RPFTOCCacheMutex );306 if (! singleton) return NULL;307 GDALDataset* ds = singleton->_GetDataset(fileName);308 ds->Reference();309 return ds;310 }311 312 static void ReleaseDataset(GDALDataset* ds)313 {314 CPLMutexHolderD( &RPFTOCCacheMutex );315 ds->Dereference();316 }317 };318 319 203 320 204 /************************************************************************/ … … 324 208 /************************************************************************/ 325 209 326 class RPFTOCProxyRasterDataSet : public GDALDataset 327 { 328 char* fileName; 329 210 class RPFTOCProxyRasterDataSet : public GDALProxyPoolDataset 211 { 330 212 /* The following parameters are only for sanity checking */ 331 213 int checkDone; 332 214 int checkOK; 333 const char* projectionRef;334 215 double nwLong, nwLat; 335 216 GDALColorTable* colorTableRef; … … 337 218 double noDataValue; 338 219 RPFTOCSubDataset* subdataset; 339 220 340 221 public: 341 222 RPFTOCProxyRasterDataSet(RPFTOCSubDataset* subdataset, … … 346 227 int nBands); 347 228 348 ~RPFTOCProxyRasterDataSet()349 {350 if (fileName)351 CPLFree(fileName);352 }353 354 229 void SetNoDataValue(double noDataValue) { 355 230 this->noDataValue = noDataValue; 356 231 bHasNoDataValue = TRUE; 357 232 } 358 233 359 234 double GetNoDataValue(int* bHasNoDataValue) 360 235 { … … 362 237 *bHasNoDataValue = this->bHasNoDataValue; 363 238 return noDataValue; 364 } 365 239 } 240 241 GDALDataset* GetUnderlyingDataset() { return GDALProxyPoolDataset::GetUnderlyingDataset(); } 242 366 243 void SetReferenceColorTable(GDALColorTable* colorTableRef) { this->colorTableRef = colorTableRef;} 367 244 368 245 const GDALColorTable* GetReferenceColorTable() { return colorTableRef; } 369 246 370 const char* GetFileName() { return fileName; }371 372 247 int SanityCheckOK(GDALDataset* sourceDS); 373 248 374 249 RPFTOCSubDataset* GetSubDataset() { return subdataset; } 375 250 }; … … 391 266 392 267 public: 393 RPFTOCProxyRasterBandRGBA( int nRasterXSize, int nRasterYSize,268 RPFTOCProxyRasterBandRGBA(GDALProxyPoolDataset* poDS, int nBand, 394 269 int nBlockXSize, int nBlockYSize) 395 270 { 396 RPFTOCGDALDatasetCache::Ref();397 this->eAccess = GA_ReadOnly;398 this->eDataType = GDT_Byte;271 this->poDS = poDS; 272 nRasterXSize = poDS->GetRasterXSize(); 273 nRasterYSize = poDS->GetRasterYSize(); 399 274 this->nBlockXSize = nBlockXSize; 400 275 this->nBlockYSize = nBlockYSize; 401 this->nRasterXSize = nRasterXSize;402 this->n RasterYSize = nRasterYSize;276 eDataType = GDT_Byte; 277 this->nBand = nBand; 403 278 blockByteSize = nBlockXSize * nBlockYSize; 404 279 initDone = FALSE; 405 280 } 406 281 407 ~RPFTOCProxyRasterBandRGBA()408 {409 RPFTOCGDALDatasetCache::Unref();410 }411 412 282 virtual GDALColorInterp GetColorInterpretation() 413 283 { … … 460 330 CPLErr ret; 461 331 RPFTOCProxyRasterDataSet* proxyDS = (RPFTOCProxyRasterDataSet*)poDS; 462 const char* fileName = proxyDS->GetFileName(); 463 GDALDataset* ds = RPFTOCGDALDatasetCache::GetDataset(fileName); 332 GDALDataset* ds = proxyDS->GetUnderlyingDataset(); 464 333 if (ds) 465 334 { 466 335 if (proxyDS->SanityCheckOK(ds) == FALSE) 467 336 { 468 RPFTOCGDALDatasetCache::ReleaseDataset(ds);469 337 return CE_Failure; 470 338 } … … 500 368 /* computing the R tile, the G tile, the B tile and the A tile */ 501 369 void* cachedImage = 502 proxyDS->GetSubDataset()->GetCachedTile( fileName, nBlockXOff, nBlockYOff);370 proxyDS->GetSubDataset()->GetCachedTile(GetDescription(), nBlockXOff, nBlockYOff); 503 371 if (cachedImage == NULL) 504 372 { 505 373 CPLDebug("RPFTOC", "Read (%d, %d) of band %d, of file %s", 506 nBlockXOff, nBlockYOff, nBand, fileName);374 nBlockXOff, nBlockYOff, nBand, GetDescription()); 507 375 ret = srcBand->ReadBlock(nBlockXOff, nBlockYOff, pImage); 508 376 if (ret == CE_None) 509 377 { 510 378 proxyDS->GetSubDataset()->SetCachedTile 511 ( fileName, nBlockXOff, nBlockYOff, pImage, blockByteSize);379 (GetDescription(), nBlockXOff, nBlockYOff, pImage, blockByteSize); 512 380 Expand(pImage, pImage); 513 381 } … … 543 411 ret = CE_Failure; 544 412 545 RPFTOCGDALDatasetCache::ReleaseDataset(ds);546 547 413 return ret; 548 414 } … … 562 428 563 429 public: 564 RPFTOCProxyRasterBandPalette( int nRasterXSize, int nRasterYSize,430 RPFTOCProxyRasterBandPalette(GDALProxyPoolDataset* poDS, int nBand, 565 431 int nBlockXSize, int nBlockYSize) 566 432 { 567 RPFTOCGDALDatasetCache::Ref();568 this->eAccess = GA_ReadOnly;569 this->eDataType = GDT_Byte;433 this->poDS = poDS; 434 nRasterXSize = poDS->GetRasterXSize(); 435 nRasterYSize = poDS->GetRasterYSize(); 570 436 this->nBlockXSize = nBlockXSize; 571 437 this->nBlockYSize = nBlockYSize; 572 this->nRasterXSize = nRasterXSize;573 this->n RasterYSize = nRasterYSize;438 eDataType = GDT_Byte; 439 this->nBand = nBand; 574 440 blockByteSize = nBlockXSize * nBlockYSize; 575 441 initDone = FALSE; 576 442 } 577 443 578 ~RPFTOCProxyRasterBandPalette()579 {580 RPFTOCGDALDatasetCache::Unref();581 }582 583 444 virtual GDALColorInterp GetColorInterpretation() 584 445 { 585 446 return GCI_PaletteIndex; 586 447 } 587 448 588 449 virtual double GetNoDataValue(int* bHasNoDataValue) 589 450 { 590 451 return ((RPFTOCProxyRasterDataSet*)poDS)->GetNoDataValue(bHasNoDataValue); 591 452 } 592 453 593 454 virtual GDALColorTable *GetColorTable() 594 455 { … … 610 471 CPLErr ret; 611 472 RPFTOCProxyRasterDataSet* proxyDS = (RPFTOCProxyRasterDataSet*)poDS; 612 const char* fileName = proxyDS->GetFileName(); 613 GDALDataset* ds = RPFTOCGDALDatasetCache::GetDataset(fileName); 473 GDALDataset* ds = proxyDS->GetUnderlyingDataset(); 614 474 if (ds) 615 475 { 616 476 if (proxyDS->SanityCheckOK(ds) == FALSE) 617 477 { 618 RPFTOCGDALDatasetCache::ReleaseDataset(ds);619 478 return CE_Failure; 620 479 } … … 633 492 CPLError( CE_Failure, CPLE_AppDefined, 634 493 "Palette for %s is different from reference palette. " 635 "Coudln't remap exactly all colors. Trying to find closest matches.\n", fileName);494 "Coudln't remap exactly all colors. Trying to find closest matches.\n", GetDescription()); 636 495 } 637 496 } … … 658 517 ret = CE_Failure; 659 518 660 RPFTOCGDALDatasetCache::ReleaseDataset(ds);661 662 519 return ret; 663 520 } … … 673 530 int nBlockXSize, int nBlockYSize, 674 531 const char* projectionRef, double nwLong, double nwLat, 675 int nBands) 532 int nBands) : 533 /* Mark as shared since the VRT will take several references if we are in RGBA mode (4 bands for this dataset) */ 534 GDALProxyPoolDataset(fileName, nRasterXSize, nRasterYSize, GA_ReadOnly, TRUE, projectionRef) 676 535 { 677 536 int i; 678 537 this->subdataset = subdataset; 679 this->fileName = CPLStrdup(fileName);680 this->nRasterXSize = nRasterXSize;681 this->nRasterYSize = nRasterYSize;682 this->eAccess = GA_ReadOnly;683 this->projectionRef = projectionRef;684 538 this->nwLong = nwLong; 685 539 this->nwLat = nwLat; … … 687 541 noDataValue = 0; 688 542 colorTableRef = NULL; 689 bShared = TRUE; 543 690 544 checkDone = FALSE; 691 545 checkOK = FALSE; … … 694 548 for(i=0;i<4;i++) 695 549 { 696 SetBand(i +1, new RPFTOCProxyRasterBandRGBA(nRasterXSize, nRasterYSize, nBlockXSize, nBlockYSize));550 SetBand(i + 1, new RPFTOCProxyRasterBandRGBA(this, i+1, nBlockXSize, nBlockYSize)); 697 551 } 698 552 } 699 553 else 700 SetBand(1, new RPFTOCProxyRasterBandPalette( nRasterXSize, nRasterYSize, nBlockXSize, nBlockYSize));554 SetBand(1, new RPFTOCProxyRasterBandPalette(this, 1, nBlockXSize, nBlockYSize)); 701 555 } 702 556 … … 705 559 /************************************************************************/ 706 560 707 #define WARN_CHECK_DS(x) do { if (!(x)) { CPLError(CE_Warning, CPLE_AppDefined, "For %s, assert '" #x "' failed", fileName); checkOK = FALSE; } } while(0)561 #define WARN_CHECK_DS(x) do { if (!(x)) { CPLError(CE_Warning, CPLE_AppDefined, "For %s, assert '" #x "' failed", GetDescription()); checkOK = FALSE; } } while(0) 708 562 709 563 int RPFTOCProxyRasterDataSet::SanityCheckOK(GDALDataset* sourceDS) … … 726 580 WARN_CHECK_DS(sourceDS->GetRasterXSize() == nRasterXSize); 727 581 WARN_CHECK_DS(sourceDS->GetRasterYSize() == nRasterYSize); 728 WARN_CHECK_DS(EQUAL(sourceDS->GetProjectionRef(), projectionRef));582 WARN_CHECK_DS(EQUAL(sourceDS->GetProjectionRef(), GetProjectionRef())); 729 583 sourceDS->GetRasterBand(1)->GetBlockSize(&src_nBlockXSize, &src_nBlockYSize); 730 584 GetRasterBand(1)->GetBlockSize(&nBlockXSize, &nBlockYSize);
