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-05-04 12:52:34 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             :  * Permission is hereby granted, free of charge, to any person obtaining a
      12             :  * copy of this software and associated documentation files (the "Software"),
      13             :  * to deal in the Software without restriction, including without limitation
      14             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15             :  * and/or sell copies of the Software, and to permit persons to whom the
      16             :  * Software is furnished to do so, subject to the following conditions:
      17             :  *
      18             :  * The above copyright notice and this permission notice shall be included
      19             :  * in all copies or substantial portions of the Software.
      20             :  *
      21             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27             :  * DEALINGS IN THE SOFTWARE.
      28             :  ****************************************************************************/
      29             : 
      30             : #include "cpl_port.h"
      31             : #include "gdal_priv.h"
      32             : 
      33             : #include <cstddef>
      34             : #include <algorithm>
      35             : #include <set>
      36             : #include <vector>
      37             : 
      38             : #include "cpl_config.h"
      39             : #include "cpl_error.h"
      40             : #include "cpl_multiproc.h"
      41             : 
      42             : //! @cond Doxygen_Suppress
      43             : 
      44             : /* ******************************************************************** */
      45             : /*                        GDALHashSetBandBlockCache                     */
      46             : /* ******************************************************************** */
      47             : 
      48             : class GDALHashSetBandBlockCache final : public GDALAbstractBandBlockCache
      49             : {
      50             :     struct BlockComparator
      51             :     {
      52             :         // Do not change this comparator, because this order is assumed by
      53             :         // tests like tiff_write_133 for flushing from top to bottom, left
      54             :         // to right.
      55   160314000 :         bool operator()(const GDALRasterBlock *const &lhs,
      56             :                         const GDALRasterBlock *const &rhs) const
      57             :         {
      58   160314000 :             if (lhs->GetYOff() < rhs->GetYOff())
      59    79733800 :                 return true;
      60    80580200 :             if (lhs->GetYOff() > rhs->GetYOff())
      61    75105300 :                 return false;
      62     5474960 :             return lhs->GetXOff() < rhs->GetXOff();
      63             :         }
      64             :     };
      65             : 
      66             :     std::set<GDALRasterBlock *, BlockComparator> m_oSet{};
      67             :     CPLLock *hLock = nullptr;
      68             : 
      69             :     CPL_DISALLOW_COPY_ASSIGN(GDALHashSetBandBlockCache)
      70             : 
      71             :   public:
      72             :     explicit GDALHashSetBandBlockCache(GDALRasterBand *poBand);
      73             :     ~GDALHashSetBandBlockCache() override;
      74             : 
      75             :     bool Init() override;
      76             :     bool IsInitOK() override;
      77             :     CPLErr FlushCache() override;
      78             :     CPLErr AdoptBlock(GDALRasterBlock *) override;
      79             :     GDALRasterBlock *TryGetLockedBlockRef(int nXBlockOff,
      80             :                                           int nYBlockYOff) override;
      81             :     CPLErr UnreferenceBlock(GDALRasterBlock *poBlock) override;
      82             :     CPLErr FlushBlock(int nXBlockOff, int nYBlockOff,
      83             :                       int bWriteDirtyBlock) override;
      84             : };
      85             : 
      86             : /************************************************************************/
      87             : /*                     GDALHashSetBandBlockCacheCreate()                */
      88             : /************************************************************************/
      89             : 
      90             : GDALAbstractBandBlockCache *
      91          70 : GDALHashSetBandBlockCacheCreate(GDALRasterBand *poBand)
      92             : {
      93          70 :     return new GDALHashSetBandBlockCache(poBand);
      94             : }
      95             : 
      96             : /************************************************************************/
      97             : /*                       GDALHashSetBandBlockCache()                    */
      98             : /************************************************************************/
      99             : 
     100          70 : GDALHashSetBandBlockCache::GDALHashSetBandBlockCache(GDALRasterBand *poBandIn)
     101             :     : GDALAbstractBandBlockCache(poBandIn),
     102             : 
     103          70 :       hLock(CPLCreateLock(LOCK_ADAPTIVE_MUTEX))
     104             : {
     105          70 : }
     106             : 
     107             : /************************************************************************/
     108             : /*                      ~GDALHashSetBandBlockCache()                    */
     109             : /************************************************************************/
     110             : 
     111         140 : GDALHashSetBandBlockCache::~GDALHashSetBandBlockCache()
     112             : {
     113          70 :     GDALHashSetBandBlockCache::FlushCache();
     114          70 :     CPLDestroyLock(hLock);
     115         140 : }
     116             : 
     117             : /************************************************************************/
     118             : /*                                  Init()                              */
     119             : /************************************************************************/
     120             : 
     121          70 : bool GDALHashSetBandBlockCache::Init()
     122             : {
     123          70 :     return true;
     124             : }
     125             : 
     126             : /************************************************************************/
     127             : /*                             IsInitOK()                               */
     128             : /************************************************************************/
     129             : 
     130     4976470 : bool GDALHashSetBandBlockCache::IsInitOK()
     131             : {
     132     4976470 :     return true;
     133             : }
     134             : 
     135             : /************************************************************************/
     136             : /*                            AdoptBlock()                              */
     137             : /************************************************************************/
     138             : 
     139     2016080 : CPLErr GDALHashSetBandBlockCache::AdoptBlock(GDALRasterBlock *poBlock)
     140             : 
     141             : {
     142     2016080 :     FreeDanglingBlocks();
     143             : 
     144     2016080 :     CPLLockHolderOptionalLockD(hLock);
     145     2016080 :     m_oSet.insert(poBlock);
     146             : 
     147     4032170 :     return CE_None;
     148             : }
     149             : 
     150             : /************************************************************************/
     151             : /*                            FlushCache()                              */
     152             : /************************************************************************/
     153             : 
     154         221 : CPLErr GDALHashSetBandBlockCache::FlushCache()
     155             : {
     156         221 :     FreeDanglingBlocks();
     157             : 
     158         221 :     CPLErr eGlobalErr = poBand->eFlushBlockErr;
     159             : 
     160         221 :     std::set<GDALRasterBlock *, BlockComparator> oOldSet;
     161             :     {
     162         442 :         CPLLockHolderOptionalLockD(hLock);
     163         221 :         oOldSet = std::move(m_oSet);
     164             :     }
     165             : 
     166         221 :     StartDirtyBlockFlushingLog();
     167     2016300 :     for (auto &poBlock : oOldSet)
     168             :     {
     169     2016080 :         if (poBlock->DropLockForRemovalFromStorage())
     170             :         {
     171     2016080 :             CPLErr eErr = CE_None;
     172             : 
     173     4032160 :             if (!m_nWriteDirtyBlocksDisabled && eGlobalErr == CE_None &&
     174     2016080 :                 poBlock->GetDirty())
     175             :             {
     176         800 :                 UpdateDirtyBlockFlushingLog();
     177         800 :                 eErr = poBlock->Write();
     178             :             }
     179             : 
     180     2016080 :             delete poBlock;
     181             : 
     182     2016080 :             if (eErr != CE_None)
     183           0 :                 eGlobalErr = eErr;
     184             :         }
     185             :     }
     186         221 :     EndDirtyBlockFlushingLog();
     187             : 
     188         221 :     WaitCompletionPendingTasks();
     189             : 
     190         442 :     return (eGlobalErr);
     191             : }
     192             : 
     193             : /************************************************************************/
     194             : /*                        UnreferenceBlock()                            */
     195             : /************************************************************************/
     196             : 
     197           0 : CPLErr GDALHashSetBandBlockCache::UnreferenceBlock(GDALRasterBlock *poBlock)
     198             : {
     199           0 :     UnreferenceBlockBase();
     200             : 
     201           0 :     CPLLockHolderOptionalLockD(hLock);
     202           0 :     m_oSet.erase(poBlock);
     203           0 :     return CE_None;
     204             : }
     205             : 
     206             : /************************************************************************/
     207             : /*                            FlushBlock()                              */
     208             : /************************************************************************/
     209             : 
     210           3 : CPLErr GDALHashSetBandBlockCache::FlushBlock(int nXBlockOff, int nYBlockOff,
     211             :                                              int bWriteDirtyBlock)
     212             : 
     213             : {
     214           6 :     GDALRasterBlock oBlockForLookup(nXBlockOff, nYBlockOff);
     215           3 :     GDALRasterBlock *poBlock = nullptr;
     216             :     {
     217           3 :         CPLLockHolderOptionalLockD(hLock);
     218           3 :         auto oIter = m_oSet.find(&oBlockForLookup);
     219           3 :         if (oIter == m_oSet.end())
     220           0 :             return CE_None;
     221           3 :         poBlock = *oIter;
     222           3 :         m_oSet.erase(oIter);
     223             :     }
     224             : 
     225           3 :     if (!poBlock->DropLockForRemovalFromStorage())
     226           0 :         return CE_None;
     227             : 
     228           3 :     CPLErr eErr = CE_None;
     229             : 
     230           3 :     if (!m_nWriteDirtyBlocksDisabled && bWriteDirtyBlock && poBlock->GetDirty())
     231           0 :         eErr = poBlock->Write();
     232             : 
     233           3 :     delete poBlock;
     234             : 
     235           3 :     return eErr;
     236             : }
     237             : 
     238             : /************************************************************************/
     239             : /*                        TryGetLockedBlockRef()                        */
     240             : /************************************************************************/
     241             : 
     242     2960290 : GDALRasterBlock *GDALHashSetBandBlockCache::TryGetLockedBlockRef(int nXBlockOff,
     243             :                                                                  int nYBlockOff)
     244             : 
     245             : {
     246     5920590 :     GDALRasterBlock oBlockForLookup(nXBlockOff, nYBlockOff);
     247             :     GDALRasterBlock *poBlock;
     248             :     {
     249     2960290 :         CPLLockHolderOptionalLockD(hLock);
     250     2960290 :         auto oIter = m_oSet.find(&oBlockForLookup);
     251     2960290 :         if (oIter == m_oSet.end())
     252     2016040 :             return nullptr;
     253      944259 :         poBlock = *oIter;
     254             :     }
     255      944258 :     if (!poBlock->TakeLock())
     256           0 :         return nullptr;
     257      944259 :     return poBlock;
     258             : }
     259             : 
     260             : //! @endcond

Generated by: LCOV version 1.14