[ https://issues.apache.org/jira/browse/JCR-2633?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15066582#comment-15066582 ]
Manfred Baedke commented on JCR-2633: ------------------------------------- Fixed in trunk with r1721196. > Modified externally exception when modifying mixinTypes with single session > --------------------------------------------------------------------------- > > Key: JCR-2633 > URL: https://issues.apache.org/jira/browse/JCR-2633 > Project: Jackrabbit Content Repository > Issue Type: Bug > Components: jackrabbit-core > Affects Versions: 1.5.7, 2.0, 2.1 > Environment: Bundle persistency manager based storage, Jackrabbit > 1.5.7 but issue also present in newer versions > Reporter: Berry van Halderen > Assignee: Manfred Baedke > Priority: Critical > Fix For: 2.10.2 > > Attachments: holdrefs.patch, issue.patch, persistMixinTypes.patch > > > When first adding mixins and later removing all mixins, a system under heavy > stress might experience a modified externally exception even though there is > only a single session into the repository. > The unit test with forced GC and shrinking of caches indicates the problem. > The unit test itself is mostly trivial, the problem arrises when you add a > mixin to a node, save it, do this again with another mixin and then remove > both mixins and in the following save the shared item state cache is shrunk, > and the garbage collectors hits at exactly the right time. In the unit test a > reference to the jcr:mixinTypes property must have been held. > What will happen is that the ItemState of the jcr:mixinTypes property will get > a modification count higher than 0 when addin the mixins. Because a reference > to the property is kept, it will not be evicted from the primary cache in the > local item state manager. When removing all mixins, an overlayed state will > be created of this ItemState. Because the state and overlayed state are > linked, the ItemState won't be dropped from the primary cache of the shared > item state manager. > But is MAY be evicted from the secondary cache implementing the LRU/FIFO > functionality. If this is the case when while persisting the changes there is > a small window where the overlayed state will be disconnected from the state. > This happens just before collecting the changelog at: > o.a.j.c.state.ItemState.disconnect():211 > o.a.j.c.state.SessionItemStateManager.disconnectTransientItemState():674 > o.a.j.c.PropertyImpl.makePersistent():143 > o.a.j.c.ItemImpl.persistTransientItems():609 > o.a.j.c.ItemImpl.save():1087 > o.a.j.c.SessionImpl.save():858 > Or in the when actually collecting the changelog in one of the methods > Changelog.{modified(),deleted() or both. I think the latter, but not really > sure. > In any case, this breaks the bondage that prevents the cached state in the > shared item state manager. > Now if the shared item state cache has been shrunk enough and the GC hits > before o.a.j.c.state.SharedItemStateManager.Update.begin():650 when the > disconnected state will be purged from the shared item state cache. Just > below line 650 the check for stale items will then cause a re-retrieval from > the persisted store of the property. Because that state will have a > modification count of 0, it will conflict with the modification count of the > mixin property type that is being persisted. > It is true that the GC needs to go off at exactly the right time and the > secondary cache needs to have shrunk to be able to evict the item. This can > however happen in extreme cases. The patch that contains the unit test > contains code that will force the purging of the item. > There is still the matter why the modcount comes back at 0 when retrieving the > property from the persistence manager, basically the assumption made in the > code between session, local, and shared item state managers, their caches, > etcetera is that the modification count in the shared item state is always > incremented, and never reset. > There is an apparent contract (partially documented) that the modification > count is to be persisted. Which is in fact the case for the InMemPersistence- > Manager, but all bundle derived persistence managers do not persist the > jcr:mixinType property at all, but just the mixintypes as part of the > nodedefinition information. This means that the jcr:mixinTypes property will > always be re-created with modcount of 0, which leads to clashes. -- This message was sent by Atlassian JIRA (v6.3.4#6332)