Coverage Report

Created: 2025-06-13 06:29

/src/gdal/gcore/gdalhashsetbandblockcache.cpp
Line
Count
Source (jump to first uncovered line)
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
        bool operator()(const GDALRasterBlock *const &lhs,
40
                        const GDALRasterBlock *const &rhs) const
41
0
        {
42
0
            if (lhs->GetYOff() < rhs->GetYOff())
43
0
                return true;
44
0
            if (lhs->GetYOff() > rhs->GetYOff())
45
0
                return false;
46
0
            return lhs->GetXOff() < rhs->GetXOff();
47
0
        }
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
GDALHashSetBandBlockCacheCreate(GDALRasterBand *poBand)
76
0
{
77
0
    return new GDALHashSetBandBlockCache(poBand);
78
0
}
79
80
/************************************************************************/
81
/*                       GDALHashSetBandBlockCache()                    */
82
/************************************************************************/
83
84
GDALHashSetBandBlockCache::GDALHashSetBandBlockCache(GDALRasterBand *poBandIn)
85
0
    : GDALAbstractBandBlockCache(poBandIn),
86
87
0
      hLock(CPLCreateLock(LOCK_ADAPTIVE_MUTEX))
88
0
{
89
0
}
90
91
/************************************************************************/
92
/*                      ~GDALHashSetBandBlockCache()                    */
93
/************************************************************************/
94
95
GDALHashSetBandBlockCache::~GDALHashSetBandBlockCache()
96
0
{
97
0
    GDALHashSetBandBlockCache::FlushCache();
98
0
    CPLDestroyLock(hLock);
99
0
}
100
101
/************************************************************************/
102
/*                                  Init()                              */
103
/************************************************************************/
104
105
bool GDALHashSetBandBlockCache::Init()
106
0
{
107
0
    return true;
108
0
}
109
110
/************************************************************************/
111
/*                             IsInitOK()                               */
112
/************************************************************************/
113
114
bool GDALHashSetBandBlockCache::IsInitOK()
115
0
{
116
0
    return true;
117
0
}
118
119
/************************************************************************/
120
/*                            AdoptBlock()                              */
121
/************************************************************************/
122
123
CPLErr GDALHashSetBandBlockCache::AdoptBlock(GDALRasterBlock *poBlock)
124
125
0
{
126
0
    FreeDanglingBlocks();
127
128
0
    CPLLockHolderOptionalLockD(hLock);
129
0
    m_oSet.insert(poBlock);
130
131
0
    return CE_None;
132
0
}
133
134
/************************************************************************/
135
/*                            FlushCache()                              */
136
/************************************************************************/
137
138
CPLErr GDALHashSetBandBlockCache::FlushCache()
139
0
{
140
0
    FreeDanglingBlocks();
141
142
0
    CPLErr eGlobalErr = poBand->eFlushBlockErr;
143
144
0
    std::set<GDALRasterBlock *, BlockComparator> oOldSet;
145
0
    {
146
0
        CPLLockHolderOptionalLockD(hLock);
147
0
        oOldSet = std::move(m_oSet);
148
0
    }
149
150
0
    StartDirtyBlockFlushingLog();
151
0
    for (auto &poBlock : oOldSet)
152
0
    {
153
0
        if (poBlock->DropLockForRemovalFromStorage())
154
0
        {
155
0
            CPLErr eErr = CE_None;
156
157
0
            if (!m_nWriteDirtyBlocksDisabled && eGlobalErr == CE_None &&
158
0
                poBlock->GetDirty())
159
0
            {
160
0
                UpdateDirtyBlockFlushingLog();
161
0
                eErr = poBlock->Write();
162
0
            }
163
164
0
            delete poBlock;
165
166
0
            if (eErr != CE_None)
167
0
                eGlobalErr = eErr;
168
0
        }
169
0
    }
170
0
    EndDirtyBlockFlushingLog();
171
172
0
    WaitCompletionPendingTasks();
173
174
0
    return (eGlobalErr);
175
0
}
176
177
/************************************************************************/
178
/*                        UnreferenceBlock()                            */
179
/************************************************************************/
180
181
CPLErr GDALHashSetBandBlockCache::UnreferenceBlock(GDALRasterBlock *poBlock)
182
0
{
183
0
    UnreferenceBlockBase();
184
185
0
    CPLLockHolderOptionalLockD(hLock);
186
0
    m_oSet.erase(poBlock);
187
0
    return CE_None;
188
0
}
189
190
/************************************************************************/
191
/*                            FlushBlock()                              */
192
/************************************************************************/
193
194
CPLErr GDALHashSetBandBlockCache::FlushBlock(int nXBlockOff, int nYBlockOff,
195
                                             int bWriteDirtyBlock)
196
197
0
{
198
0
    GDALRasterBlock oBlockForLookup(nXBlockOff, nYBlockOff);
199
0
    GDALRasterBlock *poBlock = nullptr;
200
0
    {
201
0
        CPLLockHolderOptionalLockD(hLock);
202
0
        auto oIter = m_oSet.find(&oBlockForLookup);
203
0
        if (oIter == m_oSet.end())
204
0
            return CE_None;
205
0
        poBlock = *oIter;
206
0
        m_oSet.erase(oIter);
207
0
    }
208
209
0
    if (!poBlock->DropLockForRemovalFromStorage())
210
0
        return CE_None;
211
212
0
    CPLErr eErr = CE_None;
213
214
0
    if (!m_nWriteDirtyBlocksDisabled && bWriteDirtyBlock && poBlock->GetDirty())
215
0
        eErr = poBlock->Write();
216
217
0
    delete poBlock;
218
219
0
    return eErr;
220
0
}
221
222
/************************************************************************/
223
/*                        TryGetLockedBlockRef()                        */
224
/************************************************************************/
225
226
GDALRasterBlock *GDALHashSetBandBlockCache::TryGetLockedBlockRef(int nXBlockOff,
227
                                                                 int nYBlockOff)
228
229
0
{
230
0
    GDALRasterBlock oBlockForLookup(nXBlockOff, nYBlockOff);
231
0
    GDALRasterBlock *poBlock;
232
0
    {
233
0
        CPLLockHolderOptionalLockD(hLock);
234
0
        auto oIter = m_oSet.find(&oBlockForLookup);
235
0
        if (oIter == m_oSet.end())
236
0
            return nullptr;
237
0
        poBlock = *oIter;
238
0
    }
239
0
    if (!poBlock->TakeLock())
240
0
        return nullptr;
241
0
    return poBlock;
242
0
}
243
244
//! @endcond