Skip to content

Commit eaa0df5

Browse files
committed
CORE-5718: Make TempCacheLimit setting database-wise
1 parent 0f7e567 commit eaa0df5

File tree

6 files changed

+81
-37
lines changed

6 files changed

+81
-37
lines changed

builds/install/misc/firebird.conf.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,8 @@
375375
# Although it can be increased, the value applies to each client
376376
# connection/server instance and thus consumes a lot of memory.
377377
#
378+
# Per-database configurable.
379+
#
378380
# Type: integer
379381
#
380382
#TempCacheLimit = 64M

src/common/config/config.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -428,9 +428,9 @@ int Config::getTempBlockSize()
428428
return (int) getDefaultConfig()->values[KEY_TEMP_BLOCK_SIZE];
429429
}
430430

431-
FB_UINT64 Config::getTempCacheLimit()
431+
FB_UINT64 Config::getTempCacheLimit() const
432432
{
433-
SINT64 v = (SINT64) getDefaultConfig()->values[KEY_TEMP_CACHE_LIMIT];
433+
SINT64 v = get<SINT64>(KEY_TEMP_CACHE_LIMIT);
434434
if (v < 0)
435435
{
436436
v = getServerMode() != MODE_SUPER ? 8388608 : 67108864; // bytes

src/common/config/config.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ class Config : public Firebird::RefCounted, public Firebird::GlobalStorage
228228
static int getTempBlockSize();
229229

230230
// Caching limit for the temporary data
231-
static FB_UINT64 getTempCacheLimit();
231+
FB_UINT64 getTempCacheLimit() const;
232232

233233
// Whether remote (NFS) files can be opened
234234
static bool getRemoteFileOpenAbility();

src/jrd/Database.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,9 @@ class Database : public pool_alloc<type_dbb>
434434
Firebird::SyncObject dbb_sortbuf_sync;
435435
Firebird::Array<UCHAR*> dbb_sort_buffers; // sort buffers ready for reuse
436436

437+
Firebird::Mutex dbb_temp_cache_mutex;
438+
FB_UINT64 dbb_temp_cache_size; // total size of in-memory temp space chunks (see TempSpace class)
439+
437440
TraNumber dbb_oldest_active; // Cached "oldest active" transaction
438441
TraNumber dbb_oldest_transaction; // Cached "oldest interesting" transaction
439442
TraNumber dbb_oldest_snapshot; // Cached "oldest snapshot" of all active transactions

src/jrd/TempSpace.cpp

Lines changed: 73 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -23,26 +23,64 @@
2323
#include "firebird.h"
2424

2525
#include "iberror.h"
26+
#include "../common/classes/TempFile.h"
2627
#include "../common/config/config.h"
2728
#include "../common/config/dir_list.h"
2829
#include "../common/gdsassert.h"
29-
#include "../yvalve/gds_proto.h"
30-
#include "../jrd/err_proto.h"
3130
#include "../common/isc_proto.h"
3231
#include "../common/os/path_utils.h"
32+
#include "../jrd/jrd.h"
3333

3434
#include "../jrd/TempSpace.h"
3535

36-
using Firebird::TempFile;
36+
using namespace Firebird;
37+
using namespace Jrd;
3738

3839
// Static definitions/initializations
3940

40-
const size_t MIN_TEMP_BLOCK_SIZE = 64 * 1024;
41-
42-
Firebird::GlobalPtr<Firebird::Mutex> TempSpace::initMutex;
43-
Firebird::TempDirectoryList* TempSpace::tempDirs = NULL;
41+
GlobalPtr<Mutex> TempSpace::initMutex;
42+
TempDirectoryList* TempSpace::tempDirs = NULL;
4443
FB_SIZE_T TempSpace::minBlockSize = 0;
45-
offset_t TempSpace::globalCacheUsage = 0;
44+
45+
namespace
46+
{
47+
const size_t MIN_TEMP_BLOCK_SIZE = 64 * 1024;
48+
49+
class TempCacheLimitGuard
50+
{
51+
public:
52+
explicit TempCacheLimitGuard(FB_SIZE_T size)
53+
: m_dbb(GET_DBB()), m_size(size),
54+
m_guard(m_dbb->dbb_temp_cache_mutex, FB_FUNCTION)
55+
{
56+
m_allowed = (m_dbb->dbb_temp_cache_size + size <= m_dbb->dbb_config->getTempCacheLimit());
57+
}
58+
59+
bool isAllowed() const
60+
{
61+
return m_allowed;
62+
}
63+
64+
void increment()
65+
{
66+
fb_assert(m_allowed);
67+
m_dbb->dbb_temp_cache_size += m_size;
68+
}
69+
70+
static void decrement(FB_SIZE_T size)
71+
{
72+
Database* const dbb = GET_DBB();
73+
MutexLockGuard guard(dbb->dbb_temp_cache_mutex, FB_FUNCTION);
74+
dbb->dbb_temp_cache_size -= size;
75+
}
76+
77+
private:
78+
Database* const m_dbb;
79+
FB_SIZE_T m_size;
80+
MutexLockGuard m_guard;
81+
bool m_allowed;
82+
};
83+
}
4684

4785
//
4886
// In-memory block class
@@ -98,7 +136,7 @@ FB_SIZE_T TempSpace::FileBlock::write(offset_t offset, const void* buffer, FB_SI
98136
// Constructor
99137
//
100138

101-
TempSpace::TempSpace(MemoryPool& p, const Firebird::PathName& prefix, bool dynamic)
139+
TempSpace::TempSpace(MemoryPool& p, const PathName& prefix, bool dynamic)
102140
: pool(p), filePrefix(p, prefix),
103141
logicalSize(0), physicalSize(0), localCacheUsage(0),
104142
head(NULL), tail(NULL), tempFiles(p),
@@ -107,11 +145,11 @@ TempSpace::TempSpace(MemoryPool& p, const Firebird::PathName& prefix, bool dynam
107145
{
108146
if (!tempDirs)
109147
{
110-
Firebird::MutexLockGuard guard(initMutex, FB_FUNCTION);
148+
MutexLockGuard guard(initMutex, FB_FUNCTION);
111149
if (!tempDirs)
112150
{
113151
MemoryPool& def_pool = *getDefaultMemoryPool();
114-
tempDirs = FB_NEW_POOL(def_pool) Firebird::TempDirectoryList(def_pool);
152+
tempDirs = FB_NEW_POOL(def_pool) TempDirectoryList(def_pool);
115153
minBlockSize = Config::getTempBlockSize();
116154

117155
if (minBlockSize < MIN_TEMP_BLOCK_SIZE)
@@ -137,12 +175,10 @@ TempSpace::~TempSpace()
137175
head = temp;
138176
}
139177

140-
globalCacheUsage -= localCacheUsage;
178+
TempCacheLimitGuard::decrement(localCacheUsage);
141179

142180
while (tempFiles.getCount())
143-
{
144181
delete tempFiles.pop();
145-
}
146182
}
147183

148184
//
@@ -275,18 +311,22 @@ void TempSpace::extend(FB_SIZE_T size)
275311

276312
Block* block = NULL;
277313

278-
if (globalCacheUsage + size <= size_t(Config::getTempCacheLimit()))
279-
{
280-
try
281-
{
282-
// allocate block in virtual memory
283-
block = FB_NEW_POOL(pool) MemoryBlock(FB_NEW_POOL(pool) UCHAR[size], tail, size);
284-
localCacheUsage += size;
285-
globalCacheUsage += size;
286-
}
287-
catch (const Firebird::BadAlloc&)
314+
{ // scope
315+
TempCacheLimitGuard guard(size);
316+
317+
if (guard.isAllowed())
288318
{
289-
// not enough memory
319+
try
320+
{
321+
// allocate block in virtual memory
322+
block = FB_NEW_POOL(pool) MemoryBlock(FB_NEW_POOL(pool) UCHAR[size], tail, size);
323+
localCacheUsage += size;
324+
guard.increment();
325+
}
326+
catch (const BadAlloc&)
327+
{
328+
// not enough memory
329+
}
290330
}
291331
}
292332

@@ -371,18 +411,18 @@ TempSpace::Block* TempSpace::findBlock(offset_t& offset) const
371411

372412
TempFile* TempSpace::setupFile(FB_SIZE_T size)
373413
{
374-
Firebird::StaticStatusVector status_vector;
414+
StaticStatusVector status_vector;
375415

376416
for (FB_SIZE_T i = 0; i < tempDirs->getCount(); i++)
377417
{
378418
TempFile* file = NULL;
379419

380-
Firebird::PathName directory = (*tempDirs)[i];
420+
PathName directory = (*tempDirs)[i];
381421
PathUtils::ensureSeparator(directory);
382422

383423
for (FB_SIZE_T j = 0; j < tempFiles.getCount(); j++)
384424
{
385-
Firebird::PathName dirname, filename;
425+
PathName dirname, filename;
386426
PathUtils::splitLastComponent(dirname, filename, tempFiles[j]->getName());
387427
PathUtils::ensureSeparator(dirname);
388428
if (!directory.compare(dirname))
@@ -402,7 +442,7 @@ TempFile* TempSpace::setupFile(FB_SIZE_T size)
402442

403443
file->extend(size);
404444
}
405-
catch (const Firebird::system_error& ex)
445+
catch (const system_error& ex)
406446
{
407447
ex.stuffException(status_vector);
408448
continue;
@@ -412,8 +452,8 @@ TempFile* TempSpace::setupFile(FB_SIZE_T size)
412452
}
413453

414454
// no room in all directories
415-
Firebird::Arg::Gds status(isc_out_of_temp_space);
416-
status.append(Firebird::Arg::StatusVector(status_vector.begin()));
455+
Arg::Gds status(isc_out_of_temp_space);
456+
status.append(Arg::StatusVector(status_vector.begin()));
417457
iscLogStatus(NULL, status.value());
418458
status.raise();
419459

@@ -480,7 +520,7 @@ void TempSpace::releaseSpace(offset_t position, FB_SIZE_T size)
480520
const offset_t end = position + size;
481521
fb_assert(end <= getSize()); // Block ends in file
482522

483-
if (freeSegments.locate(Firebird::locEqual, end))
523+
if (freeSegments.locate(locEqual, end))
484524
{
485525
// The next segment is found to be adjacent
486526
Segment* const next_seg = &freeSegments.current();
@@ -502,7 +542,7 @@ void TempSpace::releaseSpace(offset_t position, FB_SIZE_T size)
502542
return;
503543
}
504544

505-
if (freeSegments.locate(Firebird::locLess, position))
545+
if (freeSegments.locate(locLess, position))
506546
{
507547
// Check the prior segment for being adjacent
508548
Segment* const prior_seg = &freeSegments.current();

src/jrd/TempSpace.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,6 @@ class TempSpace : public Firebird::File
215215
static Firebird::GlobalPtr<Firebird::Mutex> initMutex;
216216
static Firebird::TempDirectoryList* tempDirs;
217217
static FB_SIZE_T minBlockSize;
218-
static offset_t globalCacheUsage;
219218
};
220219

221220
#endif // JRD_TEMP_SPACE_H

0 commit comments

Comments
 (0)