LCOV - code coverage report
Current view: top level - gcore - gdalhashsetbandblockcache.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 65 75 86.7 %
Date: 2025-10-21 22:35:35 Functions: 11 12 91.7 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL Core
       4             :  * Purpose:  Store cached blocks in a hash set
       5             :  * Author:   Even Rouault, <even dot rouault at spatialys dot org>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2010, Tamas Szekeres
       9             :  * Copyright (c) 2015, Even Rouault <even dot rouault at spatialys dot org>
      10             :  *
      11             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : 
      14             : #include "cpl_port.h"
      15             : #include "gdal_priv.h"
      16             : 
      17             : #include <cstddef>
      18             : #include <algorithm>
      19             : #include <set>
      20             : #include <vector>
      21             : 
      22             : #include "cpl_config.h"
      23             : #include "cpl_error.h"
      24             : #include "cpl_multiproc.h"
      25             : #include "gdal_abstractbandblockcache.h"
      26             : 
      27             : //! @cond Doxygen_Suppress
      28             : 
      29             : /* ******************************************************************** */
      30             : /*                        GDALHashSetBandBlockCache                     */
      31             : /* ******************************************************************** */
      32             : 
      33             : class GDALHashSetBandBlockCache final : public GDALAbstractBandBlockCache
      34             : {
      35             :     struct BlockComparator
      36             :     {
      37             :         // Do not change this comparator, because this order is assumed by
      38             :         // tests like tiff_write_133 for flushing from top to bottom, left
      39             :         // to right.
      40   160314000 :         bool operator()(const GDALRasterBlock *const &lhs,
      41             :                         const GDALRasterBlock *const &rhs) const
      42             :         {
      43   160314000 :             if (lhs->GetYOff() < rhs->GetYOff())
      44    79733800 :                 return true;
      45    80580200 :             if (lhs->GetYOff() > rhs->GetYOff())
      46    75105200 :                 return false;
      47     5474950 :             return lhs->GetXOff() < rhs->GetXOff();
      48             :         }
      49             :     };
      50             : 
      51             :     std::set<GDALRasterBlock *, BlockComparator> m_oSet{};
      52             :     CPLLock *hLock = nullptr;
      53             : 
      54             :     CPL_DISALLOW_COPY_ASSIGN(GDALHashSetBandBlockCache)
      55             : 
      56             :   public:
      57             :     explicit GDALHashSetBandBlockCache(GDALRasterBand *poBand);
      58             :     ~GDALHashSetBandBlockCache() override;
      59             : 
      60             :     bool Init() override;
      61             :     bool IsInitOK() override;
      62             :     CPLErr FlushCache() override;
      63             :     CPLErr AdoptBlock(GDALRasterBlock *) override;
      64             :     GDALRasterBlock *TryGetLockedBlockRef(int nXBlockOff,
      65             :                                           int nYBlockYOff) override;
      66             :     CPLErr UnreferenceBlock(GDALRasterBlock *poBlock) override;
      67             :     CPLErr FlushBlock(int nXBlockOff, int nYBlockOff,
      68             :                       int bWriteDirtyBlock) override;
      69             : };
      70             : 
      71             : /************************************************************************/
      72             : /*                     GDALHashSetBandBlockCacheCreate()                */
      73             : /************************************************************************/
      74             : 
      75             : GDALAbstractBandBlockCache *
      76          71 : GDALHashSetBandBlockCacheCreate(GDALRasterBand *poBand)
      77             : {
      78          71 :     return new GDALHashSetBandBlockCache(poBand);
      79             : }
      80             : 
      81             : /************************************************************************/
      82             : /*                       GDALHashSetBandBlockCache()                    */
      83             : /************************************************************************/
      84             : 
      85          71 : GDALHashSetBandBlockCache::GDALHashSetBandBlockCache(GDALRasterBand *poBandIn)
      86             :     : GDALAbstractBandBlockCache(poBandIn),
      87             : 
      88          71 :       hLock(CPLCreateLock(LOCK_ADAPTIVE_MUTEX))
      89             : {
      90          71 : }
      91             : 
      92             : /************************************************************************/
      93             : /*                      ~GDALHashSetBandBlockCache()                    */
      94             : /************************************************************************/
      95             : 
      96         142 : GDALHashSetBandBlockCache::~GDALHashSetBandBlockCache()
      97             : {
      98          71 :     GDALHashSetBandBlockCache::FlushCache();
      99          71 :     CPLDestroyLock(hLock);
     100         142 : }
     101             : 
     102             : /************************************************************************/
     103             : /*                                  Init()                              */
     104             : /************************************************************************/
     105             : 
     106          71 : bool GDALHashSetBandBlockCache::Init()
     107             : {
     108          71 :     return true;
     109             : }
     110             : 
     111             : /************************************************************************/
     112             : /*                             IsInitOK()                               */
     113             : /************************************************************************/
     114             : 
     115     4976470 : bool GDALHashSetBandBlockCache::IsInitOK()
     116             : {
     117     4976470 :     return true;
     118             : }
     119             : 
     120             : /************************************************************************/
     121             : /*                            AdoptBlock()                              */
     122             : /************************************************************************/
     123             : 
     124     2016090 : CPLErr GDALHashSetBandBlockCache::AdoptBlock(GDALRasterBlock *poBlock)
     125             : 
     126             : {
     127     2016090 :     FreeDanglingBlocks();
     128             : 
     129     2016090 :     CPLLockHolderOptionalLockD(hLock);
     130     2016090 :     m_oSet.insert(poBlock);
     131             : 
     132     4032170 :     return CE_None;
     133             : }
     134             : 
     135             : /************************************************************************/
     136             : /*                            FlushCache()                              */
     137             : /************************************************************************/
     138             : 
     139         225 : CPLErr GDALHashSetBandBlockCache::FlushCache()
     140             : {
     141         225 :     FreeDanglingBlocks();
     142             : 
     143         225 :     CPLErr eGlobalErr = poBand->eFlushBlockErr;
     144             : 
     145         225 :     std::set<GDALRasterBlock *, BlockComparator> oOldSet;
     146             :     {
     147         450 :         CPLLockHolderOptionalLockD(hLock);
     148         225 :         oOldSet = std::move(m_oSet);
     149             :     }
     150             : 
     151         225 :     StartDirtyBlockFlushingLog();
     152     2016310 :     for (auto &poBlock : oOldSet)
     153             :     {
     154     2016080 :         if (poBlock->DropLockForRemovalFromStorage())
     155             :         {
     156     2016080 :             CPLErr eErr = CE_None;
     157             : 
     158     4032160 :             if (!m_nWriteDirtyBlocksDisabled && eGlobalErr == CE_None &&
     159     2016080 :                 poBlock->GetDirty())
     160             :             {
     161         800 :                 UpdateDirtyBlockFlushingLog();
     162         800 :                 eErr = poBlock->Write();
     163             :             }
     164             : 
     165     2016080 :             delete poBlock;
     166             : 
     167     2016080 :             if (eErr != CE_None)
     168           0 :                 eGlobalErr = eErr;
     169             :         }
     170             :     }
     171         225 :     EndDirtyBlockFlushingLog();
     172             : 
     173         225 :     WaitCompletionPendingTasks();
     174             : 
     175         450 :     return (eGlobalErr);
     176             : }
     177             : 
     178             : /************************************************************************/
     179             : /*                        UnreferenceBlock()                            */
     180             : /************************************************************************/
     181             : 
     182           0 : CPLErr GDALHashSetBandBlockCache::UnreferenceBlock(GDALRasterBlock *poBlock)
     183             : {
     184           0 :     UnreferenceBlockBase();
     185             : 
     186           0 :     CPLLockHolderOptionalLockD(hLock);
     187           0 :     m_oSet.erase(poBlock);
     188           0 :     return CE_None;
     189             : }
     190             : 
     191             : /************************************************************************/
     192             : /*                            FlushBlock()                              */
     193             : /************************************************************************/
     194             : 
     195           4 : CPLErr GDALHashSetBandBlockCache::FlushBlock(int nXBlockOff, int nYBlockOff,
     196             :                                              int bWriteDirtyBlock)
     197             : 
     198             : {
     199           8 :     GDALRasterBlock oBlockForLookup(nXBlockOff, nYBlockOff);
     200           4 :     GDALRasterBlock *poBlock = nullptr;
     201             :     {
     202           4 :         CPLLockHolderOptionalLockD(hLock);
     203           4 :         auto oIter = m_oSet.find(&oBlockForLookup);
     204           4 :         if (oIter == m_oSet.end())
     205           0 :             return CE_None;
     206           4 :         poBlock = *oIter;
     207           4 :         m_oSet.erase(oIter);
     208             :     }
     209             : 
     210           4 :     if (!poBlock->DropLockForRemovalFromStorage())
     211           0 :         return CE_None;
     212             : 
     213           4 :     CPLErr eErr = CE_None;
     214             : 
     215           4 :     if (!m_nWriteDirtyBlocksDisabled && bWriteDirtyBlock && poBlock->GetDirty())
     216           0 :         eErr = poBlock->Write();
     217             : 
     218           4 :     delete poBlock;
     219             : 
     220           4 :     return eErr;
     221             : }
     222             : 
     223             : /************************************************************************/
     224             : /*                        TryGetLockedBlockRef()                        */
     225             : /************************************************************************/
     226             : 
     227     2960290 : GDALRasterBlock *GDALHashSetBandBlockCache::TryGetLockedBlockRef(int nXBlockOff,
     228             :                                                                  int nYBlockOff)
     229             : 
     230             : {
     231     5920590 :     GDALRasterBlock oBlockForLookup(nXBlockOff, nYBlockOff);
     232             :     GDALRasterBlock *poBlock;
     233             :     {
     234     2960290 :         CPLLockHolderOptionalLockD(hLock);
     235     2960290 :         auto oIter = m_oSet.find(&oBlockForLookup);
     236     2960290 :         if (oIter == m_oSet.end())
     237     2016040 :             return nullptr;
     238      944259 :         poBlock = *oIter;
     239             :     }
     240      944258 :     if (!poBlock->TakeLock())
     241           0 :         return nullptr;
     242      944259 :     return poBlock;
     243             : }
     244             : 
     245             : //! @endcond

Generated by: LCOV version 1.14