You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-issues@jackrabbit.apache.org by "Alexander Klimetschek (JIRA)" <ji...@apache.org> on 2015/09/09 00:44:46 UTC

[jira] [Comment Edited] (OAK-3374) Concurrent Updates of Group's Membership Results in Conflict

    [ https://issues.apache.org/jira/browse/OAK-3374?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14735771#comment-14735771 ] 

Alexander Klimetschek edited comment on OAK-3374 at 9/8/15 10:44 PM:
---------------------------------------------------------------------

The case where this easily occurs is when different threads/requests are adding users to the same group at the same time (for example, onboarding users from an external system via auth, and putting them into some application group).

The current patch's conflict handler is conservative and will only keep members that are in both sets (from all I can see, just looked at the code, haven't tested it). This means that if in the above case 2 requests conflict, these 2 users would NOT become members after the conflict resolution, since each request does not have the other's request member.

One would need a three-way merge with a common baseline, so it's obvious each request does an ADD compared to the baseline (with a different user) and they can be clearly separated from an (ADD userA) and (ADD userB + DELETE userA) case (which should end up with the "safe" state of userB not being a member). But I don't really know how the oak conflict handlers work...


was (Author: alexander.klimetschek):
The case where this easily occurs if different threads/requests are adding users to the same group at the same time (for example, onboarding users from an external system via auth, and putting them into some application group).

The current patch's conflict handler is conservative and will only keep members that are in both sets (from all I can see, just looked at the code, haven't tested it). This means that if in the above case 2 requests conflict, these 2 users would NOT become members after the conflict resolution, since each request does not have the other's request member.

One would need a three-way merge with a common baseline, so it's obvious each request does an ADD compared to the baseline (with a different user) and they can be clearly separated from an (ADD userA) and (ADD userB + DELETE userA) case (which should end up with the "safe" state of userB not being a member). But I don't really know how the oak conflict handlers work...

> Concurrent Updates of Group's Membership Results in Conflict
> ------------------------------------------------------------
>
>                 Key: OAK-3374
>                 URL: https://issues.apache.org/jira/browse/OAK-3374
>             Project: Jackrabbit Oak
>          Issue Type: Bug
>          Components: core, security
>    Affects Versions: 1.3.5
>            Reporter: Dominique Jäggi
>            Assignee: Dominique Jäggi
>         Attachments: OAK-3374_-_Concurrent_Updates_of_Group_s_Membership_Results_in_Conflict.patch
>
>
> when concurrently updating the _rep:members_ property of a group principal, a merge conflict occurs:
> {noformat}
> Caused by: org.apache.jackrabbit.oak.api.CommitFailedException: OakState0001: Unresolved conflicts in /home/groups/a/administrators
> 	at org.apache.jackrabbit.oak.plugins.commit.ConflictValidator.failOnMergeConflict(ConflictValidator.java:84)
> 	at org.apache.jackrabbit.oak.plugins.commit.ConflictValidator.propertyChanged(ConflictValidator.java:60)
> 	at org.apache.jackrabbit.oak.spi.commit.CompositeEditor.propertyChanged(CompositeEditor.java:91)
> 	at org.apache.jackrabbit.oak.spi.commit.EditorDiff.propertyChanged(EditorDiff.java:93)
> 	at org.apache.jackrabbit.oak.plugins.segment.SegmentNodeState.compareProperties(SegmentNodeState.java:596)
> 	at org.apache.jackrabbit.oak.plugins.segment.SegmentNodeState.compareAgainstBaseState(SegmentNodeState.java:456)
> 	at org.apache.jackrabbit.oak.spi.commit.EditorDiff.childNodeChanged(EditorDiff.java:148)
> 	at org.apache.jackrabbit.oak.plugins.segment.MapRecord.compare(MapRecord.java:418)
> 	at org.apache.jackrabbit.oak.plugins.segment.SegmentNodeState.compareAgainstBaseState(SegmentNodeState.java:583)
> 	at org.apache.jackrabbit.oak.spi.commit.EditorDiff.childNodeChanged(EditorDiff.java:148)
> 	at org.apache.jackrabbit.oak.plugins.segment.MapRecord.compare(MapRecord.java:418)
> 	at org.apache.jackrabbit.oak.plugins.segment.SegmentNodeState.compareAgainstBaseState(SegmentNodeState.java:583)
> 	at org.apache.jackrabbit.oak.spi.commit.EditorDiff.childNodeChanged(EditorDiff.java:148)
> 	at org.apache.jackrabbit.oak.plugins.segment.MapRecord.compare(MapRecord.java:418)
> 	at org.apache.jackrabbit.oak.plugins.segment.SegmentNodeState.compareAgainstBaseState(SegmentNodeState.java:583)
> 	at org.apache.jackrabbit.oak.spi.commit.EditorDiff.childNodeChanged(EditorDiff.java:148)
> 	at org.apache.jackrabbit.oak.plugins.segment.MapRecord.compare(MapRecord.java:487)
> 	at org.apache.jackrabbit.oak.plugins.segment.SegmentNodeState.compareAgainstBaseState(SegmentNodeState.java:583)
> 	at org.apache.jackrabbit.oak.spi.commit.EditorDiff.process(EditorDiff.java:52)
> 	at org.apache.jackrabbit.oak.spi.commit.EditorHook.processCommit(EditorHook.java:54)
> 	at org.apache.jackrabbit.oak.spi.commit.CompositeHook.processCommit(CompositeHook.java:61)
> 	at org.apache.jackrabbit.oak.spi.commit.CompositeHook.processCommit(CompositeHook.java:61)
> 	at org.apache.jackrabbit.oak.plugins.segment.SegmentNodeStore$Commit.prepare(SegmentNodeStore.java:405)
> 	at org.apache.jackrabbit.oak.plugins.segment.SegmentNodeStore$Commit.optimisticMerge(SegmentNodeStore.java:428)
> 	at org.apache.jackrabbit.oak.plugins.segment.SegmentNodeStore$Commit.execute(SegmentNodeStore.java:484)
> 	at org.apache.jackrabbit.oak.plugins.segment.SegmentNodeStore.merge(SegmentNodeStore.java:162)
> 	at org.apache.jackrabbit.oak.spi.state.ProxyNodeStore.merge(ProxyNodeStore.java:43)
> 	at org.apache.jackrabbit.oak.core.MutableRoot.commit(MutableRoot.java:247)
> 	at org.apache.jackrabbit.oak.jcr.delegate.SessionDelegate.commit(SessionDelegate.java:313)
> 	at org.apache.jackrabbit.oak.jcr.delegate.SessionDelegate.save(SessionDelegate.java:459)
> 	... 77 common frames omitted
> {noformat}



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)