jackrabbit-oak-issues mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Alexander Klimetschek (JIRA)" <j...@apache.org>
Subject [jira] [Comment Edited] (OAK-3374) Concurrent Updates of Group's Membership Results in Conflict
Date Tue, 08 Sep 2015 22:46:46 GMT

    [ 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:46 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 oauth,
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 (with 2 different users added), these 2 users would
NOT become members after the conflict resolution, since each request = session state does
not have the other's request member. This would not be good for the use case – currently,
the session save fails due to the conflict, so this issue is visible, with a conflict handler
it would silently get dropped and all you see is that membership updates never came through.

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 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 oauth,
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 (with 2 different users added), these 2 users would
NOT become members after the conflict resolution, since each request = session state does
not have the other's request member. This would not be good for the use case (currently, the
session save fails due to the conflict, so this issue is visible, with a conflict handler
it would silently get dropped and all you see is that membership updates never came through).

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)

Mime
View raw message