Skip to content

[#1067] Ask the memory quota whether an explicit db-cache-size fits instead of taking it - #1070

Merged
vharseko merged 1 commit into
OpenIdentityPlatform:masterfrom
vharseko:issues/1067-je-cache-size-probe-leaks-server-quota
Sep 23, 2026
Merged

vharseko merged 1 commit into
OpenIdentityPlatform:masterfrom
vharseko:issues/1067-je-cache-size-probe-leaks-server-quota

Conversation

@vharseko

Copy link
Copy Markdown
Member

Fixes #1067

What

ConfigurableEnvironment.validateDbCacheSize checked an explicit db-cache-size against the server's memory quota with acquireMemory - a reservation - and nothing gave it back. JEStorage.buildConfiguration reserves the same size again four lines later, on purpose, and close() releases only that one, so every open of a JE backend with an explicit size (each enable, each import-ldif or rebuild-index of a disabled backend; twice for an import with include/exclude branches, which opens the storage once more to migrate them) drained one cache size from what the server believed it had left.

The check is now the probe it was meant to be - isMemoryAvailable takes and gives back in one call - and the warning it logs names what the quota has left (getAvailableMemory()), as its text says ("the JVM has only %d available") and as the same warning from isConfigurationAcceptable does, rather than the size of the old generation (getMaxMemory()).

The reservation dates from OPENDJ-1727 (2015-03), which added it for the local-db backend that had no reservation of its own; OPENDJ-1719 (2015-09) kept it while giving JEStorage one. Wren:DS carries the same reservation.

Dropping the check altogether was the other option in the issue; it is kept because at startup the open of a backend is not checked against the quota beforehand, and a refused reservation in buildConfiguration is silent - the warning is the only word the operator gets that an explicit size did not fit.

Test

ConfigurableEnvironmentTest pins parseConfigEntry against the server's own quota - the one the check reaches through DirectoryServer, which the mock quota JEStorageTest/PDBStorageTest watch does not see, which is why none of them caught this:

  • anExplicitCacheSizeTakesNothingFromTheQuota - RED before the fix: 192 MB → 128 MB after one parse;
  • aCachePercentTakesNothingFromTheQuota - the percent road never went through the check;
  • aCacheSizeTheQuotaCannotGrantIsWarnedAboutWithWhatIsLeft - the quota filled to half a cache size, the warning is logged with what is left and nothing is taken - RED before the fix: the warning said "the JVM has only 536870912 available" (the old generation) while the quota had 32 MB.

Regression, one JVM per class, all green: JETestCase 35, EncryptedJETestCase 35, ID2ChildrenCountTest 4, DN2IDTest 7, StateTest 8, OnDiskMergeImporterTest 29, ReplayedConfigChangeTest 12, ControlsTestCase 82, PDBStorageTest 10.

Related

…db-cache-size fits instead of taking it

ConfigurableEnvironment.validateDbCacheSize checked an explicit db-cache-size against the server's
memory quota with acquireMemory, which reserves the size, and nothing gave that reservation back:
JEStorage.buildConfiguration reserves the same size again, on purpose, four lines later, and close()
releases only that one. Every open of a JE backend with an explicit size - each enable, each
import-ldif or rebuild-index of a disabled backend - drained one cache size from what the server
believed it had left, until a change or a new backend was refused for memory the server had.

The check is now the probe it was meant to be - isMemoryAvailable takes and gives back in one call -
and the warning it logs names what the quota has left, as its text says and as the same warning
from isConfigurationAcceptable does, rather than the size of the old generation.

The reservation dates from OPENDJ-1727, which added it for the local-db backend that had no
reservation of its own; OPENDJ-1719 kept it while giving JEStorage one.

ConfigurableEnvironmentTest pins parseConfigEntry against the server's own quota - the one the
check reaches through DirectoryServer, which the mock quota the storage tests watch does not see:
an explicit size and a percent take nothing, and a size the quota cannot grant is warned about with
what is left, and still takes nothing.
@vharseko vharseko added bug tests Test suites: fixing, enabling, un-disabling java Changes to Java sources labels Sep 18, 2026

@maximthomas maximthomas left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

praise: the leak is closed where it starts, and the test watches the quota the check actually reaches.

  • parseConfigEntry has one production caller, JEStorage.buildConfiguration:760, which reserves the size itself at :767 — the reservation in validateDbCacheSize could only leak, and isMemoryAvailable (MemoryQuota:80-91, acquire + release) is the right replacement.
  • The warning now passes getAvailableMemory(), which is what its text ("the JVM has only %d available") says.
  • ConfigurableEnvironmentTest reads the server's own quota through DirectoryServer, which the mock quota in JEStorageTest/PDBStorageTest never sees; green on every Linux cell of run 35307742961.

@vharseko
vharseko merged commit 7243713 into OpenIdentityPlatform:master Sep 23, 2026
24 checks passed
@vharseko
vharseko deleted the issues/1067-je-cache-size-probe-leaks-server-quota branch September 23, 2026 12:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug java Changes to Java sources tests Test suites: fixing, enabling, un-disabling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

A JE backend with an explicit db-cache-size takes that size from the server's memory quota twice per open and gives it back once

2 participants