[#993] Register an entry container's configuration listeners only once it has opened - #999
Open
vharseko wants to merge 1 commit into
Conversation
…n listeners only once it has opened EntryContainer registered itself and its two configuration managers from its constructor, and only close() takes them off again. open() caught StorageRuntimeException alone, so a ConfigException - a VLV filter or sort order which does not parse, an index type the attribute has no matching rule for - left a container nothing holds a reference to, registered on the configuration of a backend which did not start. Register the five at the end of a successful open() instead, and catch every failure there rather than the storage ones alone. Hold each index in its map before opening it: an attribute index registers its listener at the end of open() and a VLV index from its constructor, so the one being opened was not yet one close() could find - the hole the existing catch already had. RootContainer gives back what a failed open took: the entry containers it registered, its own listener and the storage, the last only when this call is what opened it. openAndRegisterEntryContainers runs inside a write the storage may replay, so it now gives up what a rolled back attempt registered before opening again; without it a write-write conflict failed the backend with ERR_ENTRY_CONTAINER_ALREADY_REGISTERED. Fixes OpenIdentityPlatform#993
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #993.
The defect
EntryContainerregistered itself and its two configuration managers as listeners of the backendconfiguration from its constructor, and only
close()takes them off again.open()caughtStorageRuntimeExceptionalone, while it is declared to throwConfigExceptionand really does -an index type the attribute has no matching rule for, an index protecting both its keys and its
values, and (the most reachable of the three) a VLV filter or sort order which does not parse.
Neither
RootContainer.openEntryContainernoropenAndRegisterEntryContainerscatches it either,so the container is registered nowhere and nothing will ever call its
close().Two things in the report needed correcting, and both are in the analysis on the
issue: the
failure is not a
NullPointerException-id2entryis assigned by the first statement of thetry- and it is more than five listeners, since every index the failed open got throughregistered one of its own. What it costs is worse than an NPE:
ConfigurationHandler.replaceEntryasks every listener on the backend entry whether a change isacceptable and a single
falserejects the whole modify, so an abandoned container can veto achange on the live backend; and past that gate the entry is already stored, so a failure from one
listener turns a change the live container applied into
ERR_CONFIG_FILE_MODIFY_APPLY_FAILED.The change
EntryContaineropen(). A containerwhich did not open is not one a configuration change has anything to be applied to, and nothing
can reach it in between:
open()is called before anything holds it.open()catches every failure rather than the storage ones alone, so aConfigExceptionalsogoes through
close().the end of
open()and a VLV index from its constructor, so the one being opened was not yet oneclose()could find - the hole theStorageRuntimeExceptioncatch already had.RootContaineropen()gives back what it took: the entry containers it registered, its own listener,and the storage - the last only when this call is what opened it, since a read only root
container is opened over the very storage instance the backend holds. Nothing else reclaims any
of it:
newRootContainerthrows the instance away andBackendConfigManagerreleases the sharedlock without calling
closeBackend()for a backend which never opened, so a volume left openhere is one no later attempt to enable that backend can take.
openAndRegisterEntryContainersruns inside the writeStorage.writemay replay, so it gives upwhat a rolled back attempt registered before opening again. Without it an ordinary write-write
conflict during startup fails the backend with
ERR_ENTRY_CONTAINER_ALREADY_REGISTEREDandleaves that attempt's containers registered - the same shape
BackendImpl.changeBaseDNTreesalready uses for the containers it opens inside a write.
The base DN path needs nothing of its own: a container whose
open()throws now closes itself, sothe container
changeBaseDNTreesnever gets to put increatedis reclaimed too.Tests
FailedBackendOpenTest, five tests, each watched to fail first:aBackendWhichFailsToOpenLeavesNothingRegisteredanIndexWhichFailsToOpenLeavesNoListenerBehind/dc=com,dc=b993/vlv.vlv1left registeredaBackendWhichFailsToOpenGivesBackTheStorageItOpenedaRootContainerWhichCouldNotOpenTheStorageDoesNotCloseItaReplayedOpenLeavesOneSetOfEntryContainersAn entry container named 'dc=com,dc=b993' is alreadly registeredRun green with them:
PDBTestCase35/35,EncryptedPDBTestCase35/35,ReplayedConfigChangeTest12/12,
PDBStorageTest10/10,OnDiskMergeImporterTest29/29,PersistentCompressedSchemaTest,DN2IDTest,StateTest,ID2EntryTest,ID2ChildrenCountTest,BulkCursorTest,DefaultIndexTest.