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

Generated by: LCOV version 1.14