From 27c6a37fde2814b6f45fb78992bdf84e96382c5f Mon Sep 17 00:00:00 2001 From: chacha21 Date: Fri, 8 Dec 2023 15:02:44 +0100 Subject: [PATCH] added DropCache to GDALDataset DropCache() release cache blocks but does not write cache to disk. It is similar tp FlushCache(true) but does not assume that the dataset will be closed. --- gcore/gdal.h | 1 + gcore/gdal_priv.h | 10 ++++- gcore/gdalarraybandblockcache.cpp | 2 +- gcore/gdaldataset.cpp | 53 ++++++++++++++++++++++++ gcore/gdalhashsetbandblockcache.cpp | 4 +- gcore/gdalrasterband.cpp | 62 +++++++++++++++++++++++++++++ 6 files changed, 127 insertions(+), 5 deletions(-) diff --git a/gcore/gdal.h b/gcore/gdal.h index 8d3725752cc4..427b9bbbef04 100644 --- a/gcore/gdal.h +++ b/gcore/gdal.h @@ -1545,6 +1545,7 @@ CPLErr CPL_DLL CPL_STDCALL GDALComputeRasterMinMax(GDALRasterBandH hBand, int bApproxOK, double adfMinMax[2]); CPLErr CPL_DLL CPL_STDCALL GDALFlushRasterCache(GDALRasterBandH hBand); +CPLErr CPL_DLL CPL_STDCALL GDALDropRasterCache(GDALRasterBandH hBand); CPLErr CPL_DLL CPL_STDCALL GDALGetRasterHistogram( GDALRasterBandH hBand, double dfMin, double dfMax, int nBuckets, int *panHistogram, int bIncludeOutOfRange, int bApproxOK, diff --git a/gcore/gdal_priv.h b/gcore/gdal_priv.h index 78d4f7e1d734..f976d6c62df2 100644 --- a/gcore/gdal_priv.h +++ b/gcore/gdal_priv.h @@ -537,6 +537,7 @@ class CPL_DLL GDALDataset : public GDALMajorObject Bands GetBands(); virtual CPLErr FlushCache(bool bAtClosing = false); + virtual CPLErr DropCache(); virtual GIntBig GetEstimatedRAMUsage(); @@ -1188,7 +1189,7 @@ class GDALAbstractBandBlockCache int m_nInitialDirtyBlocksInFlushCache = 0; int m_nLastTick = -1; - bool m_bWriteDirtyBlocks = true; + size_t m_bWriteDirtyBlocksDisabled = 0; void FreeDanglingBlocks(); void UnreferenceBlockBase(); @@ -1205,9 +1206,13 @@ class GDALAbstractBandBlockCache void AddBlockToFreeList(GDALRasterBlock *); void IncDirtyBlocks(int nInc); void WaitCompletionPendingTasks(); + void EnableDirtyBlockWriting() + { + --m_bWriteDirtyBlocksDisabled; + } void DisableDirtyBlockWriting() { - m_bWriteDirtyBlocks = false; + ++m_bWriteDirtyBlocksDisabled; } bool HasDirtyBlocks() const { @@ -1412,6 +1417,7 @@ class CPL_DLL GDALRasterBand : public GDALMajorObject // New OpengIS CV_SampleDimension stuff. virtual CPLErr FlushCache(bool bAtClosing = false); + virtual CPLErr DropCache(); virtual char **GetCategoryNames(); virtual double GetNoDataValue(int *pbSuccess = nullptr); virtual int64_t GetNoDataValueAsInt64(int *pbSuccess = nullptr); diff --git a/gcore/gdalarraybandblockcache.cpp b/gcore/gdalarraybandblockcache.cpp index 94f3442cbd44..465d0c74d947 100644 --- a/gcore/gdalarraybandblockcache.cpp +++ b/gcore/gdalarraybandblockcache.cpp @@ -442,7 +442,7 @@ CPLErr GDALArrayBandBlockCache::FlushBlock(int nXBlockOff, int nYBlockOff, CPLErr eErr = CE_None; - if (m_bWriteDirtyBlocks && bWriteDirtyBlock && poBlock->GetDirty()) + if (!m_bWriteDirtyBlocksDisabled && bWriteDirtyBlock && poBlock->GetDirty()) { UpdateDirtyBlockFlushingLog(); diff --git a/gcore/gdaldataset.cpp b/gcore/gdaldataset.cpp index 888ae00d2451..5f01d4dac94f 100644 --- a/gcore/gdaldataset.cpp +++ b/gcore/gdaldataset.cpp @@ -613,6 +613,59 @@ CPLErr CPL_STDCALL GDALFlushCache(GDALDatasetH hDS) return GDALDataset::FromHandle(hDS)->FlushCache(false); } +/************************************************************************/ +/* DropCache() */ +/************************************************************************/ + +/** +* \brief Drop all write cached data +* +* This method is the same as the C function GDALDropCache(). +* +* @return CE_None in case of success +*/ + +CPLErr GDALDataset::DropCache() + +{ + CPLErr eErr = CE_None; + // This sometimes happens if a dataset is destroyed before completely + // built. + + if (papoBands) + { + for (int i = 0; i < nBands; ++i) + { + if (papoBands[i]) + { + if (papoBands[i]->DropCache() != CE_None) + eErr = CE_Failure; + } + } + } + + return eErr; +} + +/************************************************************************/ +/* GDALDropCache() */ +/************************************************************************/ + +/** +* \brief Drop all write cached data +* +* @see GDALDataset::DropCache(). +* @return CE_None in case of success +*/ + +CPLErr CPL_STDCALL GDALDropCache(GDALDatasetH hDS) + +{ + VALIDATE_POINTER1(hDS, "GDALDropCache", CE_Failure); + + return GDALDataset::FromHandle(hDS)->DropCache(); +} + /************************************************************************/ /* GetEstimatedRAMUsage() */ /************************************************************************/ diff --git a/gcore/gdalhashsetbandblockcache.cpp b/gcore/gdalhashsetbandblockcache.cpp index 8e26c0409217..711374d0fa9a 100644 --- a/gcore/gdalhashsetbandblockcache.cpp +++ b/gcore/gdalhashsetbandblockcache.cpp @@ -170,7 +170,7 @@ CPLErr GDALHashSetBandBlockCache::FlushCache() { CPLErr eErr = CE_None; - if (m_bWriteDirtyBlocks && eGlobalErr == CE_None && + if (!m_bWriteDirtyBlocksDisabled && eGlobalErr == CE_None && poBlock->GetDirty()) { UpdateDirtyBlockFlushingLog(); @@ -227,7 +227,7 @@ CPLErr GDALHashSetBandBlockCache::FlushBlock(int nXBlockOff, int nYBlockOff, CPLErr eErr = CE_None; - if (m_bWriteDirtyBlocks && bWriteDirtyBlock && poBlock->GetDirty()) + if (!m_bWriteDirtyBlocksDisabled && bWriteDirtyBlock && poBlock->GetDirty()) eErr = poBlock->Write(); delete poBlock; diff --git a/gcore/gdalrasterband.cpp b/gcore/gdalrasterband.cpp index 897d1561a565..5363002679f6 100644 --- a/gcore/gdalrasterband.cpp +++ b/gcore/gdalrasterband.cpp @@ -1140,6 +1140,68 @@ CPLErr CPL_STDCALL GDALFlushRasterCache(GDALRasterBandH hBand) return GDALRasterBand::FromHandle(hBand)->FlushCache(false); } +/************************************************************************/ +/* DropCache() */ +/************************************************************************/ + +/** +* \brief Drop raster data cache : data in cache will be lost. +* +* This call will recover memory used to cache data blocks for this raster +* band, and ensure that new requests are referred to the underlying driver. +* +* This method is the same as the C function GDALDropRasterCache(). +* +* @return CE_None on success. +*/ + +CPLErr GDALRasterBand::DropCache() + +{ + CPLErr result = CE_None; + + if (poBandBlockCache) + poBandBlockCache->DisableDirtyBlockWriting(); + + CPLErr eGlobalErr = eFlushBlockErr; + + if (eFlushBlockErr != CE_None) + { + ReportError( + eFlushBlockErr, CPLE_AppDefined, + "An error occurred while writing a dirty block from DropCache"); + eFlushBlockErr = CE_None; + } + + if (poBandBlockCache == nullptr || !poBandBlockCache->IsInitOK()) + result = eGlobalErr; + else + result = poBandBlockCache->FlushCache(); + + if (poBandBlockCache) + poBandBlockCache->EnableDirtyBlockWriting(); + + return result; +} + +/************************************************************************/ +/* GDALDropRasterCache() */ +/************************************************************************/ + +/** +* \brief Drop raster data cache. +* +* @see GDALRasterBand::DropCache() +*/ + +CPLErr CPL_STDCALL GDALDropRasterCache(GDALRasterBandH hBand) + +{ + VALIDATE_POINTER1(hBand, "GDALDropRasterCache", CE_Failure); + + return GDALRasterBand::FromHandle(hBand)->DropCache(); +} + /************************************************************************/ /* UnreferenceBlock() */ /* */