Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 353691

Summary: Add lock notifications and lock caching
Product: [Modeling] EMF Reporter: Caspar D. <caspar_d>
Component: cdo.coreAssignee: Caspar D. <caspar_d>
Status: CLOSED FIXED QA Contact: Eike Stepper <stepper>
Severity: enhancement    
Priority: P3 CC: saulius.tvarijonas, smcduff, stephane.fournier, stepper
Version: 4.1Flags: stepper: review-
stepper: review+
stepper: review+
Target Milestone: ---   
Hardware: All   
OS: All   
Whiteboard: Power to the People
Bug Depends on:    
Bug Blocks: 355287, 351912, 354454, 354854    
Attachments:
Description Flags
Patch v1
none
Patch v2
none
Patch v3
none
Patch v4
none
Patch v5
none
Patch v6
none
Patch v7
none
Patch v8
none
Patch v9
none
Patch v10
none
Patch v11 (incremental)
none
Patch v12 (incremental)
none
Patch v13 (incremental) none

Description Caspar D. CLA 2011-08-03 00:45:48 EDT
When an object gets locked/unlocked by some client, other clients
do not get notified about this. I propose to add a notification
mechanism for this.
Comment 1 Caspar D. CLA 2011-08-03 02:43:27 EDT
What I have so far, I have committed on my dev-branch:

https://dev.eclipse.org/svnroot/modeling/org.eclipse.emf.cdo/branches/cdegroot-development
Comment 2 Caspar D. CLA 2011-08-03 06:10:22 EDT
The notifications imply that there's a client-side lockState
to be updated. Currently, that lockState is not kept anywhere,
unless the client app maintains its own hard references to the
CDOLock instances. We'll have to add a lock cache before the
notifications can be useful.

Updating Bugzilla title accordingly.
Comment 3 Caspar D. CLA 2011-08-04 01:09:55 EDT
For apps that plan to use locks, it would be nice if the lockState(s)
got loaded together with the object(s), in one signal.
Comment 4 Caspar D. CLA 2011-08-04 01:14:05 EDT
* Lock notifications should be optional, and disabled by default.
Comment 5 Caspar D. CLA 2011-08-04 03:10:27 EDT
* The protocol.lockObjects and protocol.unlockObjects should probably
return the new lockStates. That would be safer and easier than changing
the lockState on the client side, as that would increase the opportunity
for discrepancies between the client and server side lockStates.
Comment 6 Caspar D. CLA 2011-08-04 03:54:57 EDT
* On the server side, locks may be held by durableViews, which have
  neither sessions nor viewIDs. We need to communicate something 
  meaningful about such lock owners nevertheles... Needs thought.
Comment 7 Caspar D. CLA 2011-08-08 03:05:18 EDT
* Switching to a different branch should invalidate all cached lock state.
Comment 8 Eike Stepper CLA 2011-08-08 08:16:26 EDT
(In reply to comment #7)
> * Switching to a different branch should invalidate all cached lock state.

And it should presumingly *release* all locks held in the old branch.
Comment 9 Caspar D. CLA 2011-08-10 04:48:53 EDT
Created attachment 201217 [details]
Patch v1

I'm attaching a fairly complete version of this big patch, for an early
review. This has only been tested against "CDO AllTests (MEM Branching)".
Probably there are a few things to iron out before it'll work well with
all test configs. I'll work on that.

Note that this patch includes some of the work on Bug 351912. It's become
hard to disentangle because I started work on that bug first, which
revealed the need for notifications, caching etc... so it's all one big
undertaking. Hope you don't mind.
Comment 10 Caspar D. CLA 2011-08-10 05:08:54 EDT
Created attachment 201219 [details]
Patch v2

Slight change so that it works with "CDO AllTests (MEM audit)"
and "CDO AllTests (MEM non-audit)" as well.

Tried "CDO AllTests (H2 branching)" too.. looks good mostly. A
few failures but I doubt they're related.
Comment 11 Caspar D. CLA 2011-08-10 05:45:10 EDT
Created attachment 201222 [details]
Patch v3

I included the new classes this time... that might help ;-)
Comment 12 Eike Stepper CLA 2011-08-10 11:49:28 EDT
Created attachment 201253 [details]
Patch v4
Comment 13 Eike Stepper CLA 2011-08-10 11:51:47 EDT
The patch is quite large and I did not look at all changes for now. I reviewed the changes to cdo.common completely and focused on the cdo client then. Here are my findings so far (I've added a number of other changes in patch v4, too):

RWOLockManager
============

These should not be synchronized:

lock(LockType, CONTEXT, Collection<? extends OBJECT>, long)
lock2(LockType, CONTEXT, Collection<? extends OBJECT>, long)
lock(LockType, CONTEXT, OBJECT, long)

See the code in the method body:

    // Must come before the synchronized block!
    long startTime = timeout == WAIT ? 0L : currentTimeMillis();

    // Do not synchronize the entire method as it would corrupt the timeout!
    synchronized (this)
    {
     ...
     

RWOLockManager
============

- Add IRWOLockManager interface


CDOLockInfo
========

- getOperation() should be an enum type (LOCK|UNLOCK)
- this seems to impact a bunch of other methods, too.


CDOLockState
=========

Are these supposed to be regular API:

org.eclipse.emf.cdo.common.lock.CDOLockState.setWriteLockOwner(CDOLockOwner)
org.eclipse.emf.cdo.common.lock.CDOLockState.setOptionOwner(CDOLockOwner)


CDOLockOwnerImpl
=============

We should discuss hashCode() and equals(). They look inefficient.


CDOViewImpl
=========

CDOViewImpl.OptionsImpl.setLockNotificationEnabled(boolean) does not fire an options event. Compare CDOViewImpl.OptionsImpl.setInvalidationPolicy(CDOInvalidationPolicy)

CDOLocksChangedEvent
================

Do we need CDOLocksChangedEvent.getBranch()? Can it be different from getView().getBranch()? Compare CDOViewInvalidationEvent.
Comment 14 Caspar D. CLA 2011-08-11 00:20:31 EDT
(In reply to comment #13)
> RWOLockManager
> ============
> These should not be synchronized:
> lock(LockType, CONTEXT, Collection<? extends OBJECT>, long)
> lock2(LockType, CONTEXT, Collection<? extends OBJECT>, long)
> lock(LockType, CONTEXT, OBJECT, long)

Fixed accordingly.

> RWOLockManager
> ============
> - Add IRWOLockManager interface

Done.

> CDOLockInfo
> ========
> - getOperation() should be an enum type (LOCK|UNLOCK)
> - this seems to impact a bunch of other methods, too.

Done.

> CDOLockState
> =========
> Are these supposed to be regular API:
> org.eclipse.emf.cdo.common.lock.CDOLockState.setWriteLockOwner(CDOLockOwner)
> org.eclipse.emf.cdo.common.lock.CDOLockState.setOptionOwner(CDOLockOwner)

No, you're right, they shouldn't be. I've created InternalCDOLockState and
moved them there. But that still left the readLockOwners exposed through the
regular API, an ugly inconsistency that I addressed by adding
add/removeReadLockOwner to the SPI interface, and returning an unmodifiable
set from the getter in the regular interface.

> CDOLockOwnerImpl
> =============
> We should discuss hashCode() and equals(). They look inefficient.

Re hashCode: replaced it with something simple but effective.

Re equals: How is a comparison of 2 integers "inefficient"? Or do you
mean the method calls to fetch those integers? Eliminating the latter
is only possible by requiring the "other" object to be of the 
same implementation class -- and I actually prefer such strictness but
I thought it would run contrary to your penchant for interfaces...

> CDOViewImpl
> =========
> CDOViewImpl.OptionsImpl.setLockNotificationEnabled(boolean) does not fire an
> options event. Compare
> CDOViewImpl.OptionsImpl.setInvalidationPolicy(CDOInvalidationPolicy)

Added the notification. Enhanced test to verify the event.

> CDOLocksChangedEvent
> ================
> Do we need CDOLocksChangedEvent.getBranch()? Can it be different from
> getView().getBranch()? Compare CDOViewInvalidationEvent.

No, it can't be different. I've removed it.

Attaching new patch in a minute.
Comment 15 Caspar D. CLA 2011-08-11 00:33:09 EDT
Created attachment 201289 [details]
Patch v5
Comment 16 Caspar D. CLA 2011-08-11 00:45:41 EDT
TODO: Add tests for NEW and TRANSIENT objects.
Comment 17 Caspar D. CLA 2011-08-11 01:42:58 EDT
Created attachment 201291 [details]
Patch v6

Legacy tests now passing.
Comment 18 Caspar D. CLA 2011-08-11 01:47:11 EDT
AllTests now passing. (There's one failure but it's not caused by this patch.)
Comment 19 Eike Stepper CLA 2011-08-11 02:19:18 EDT
Thanks for addressing my comments so quickly. I'm rejecting the review now just so that you're able to request it again later.

Regarding the efficiency of hashCode() and equals() I was mostly referring to the hashCode() method. But I noticed that your equals method differs slightly from our "standard" idiom, e.g.,

  @Override
  public boolean equals(Object obj)
  {
    if (obj == this)
    {
      return true;
    }

    if (obj instanceof CDOBranch)
    {
      CDOBranch that = (CDOBranch)obj;
      return id == that.getID();
    }

    return false;
  }
Comment 20 Caspar D. CLA 2011-08-11 02:33:23 EDT
Created attachment 201293 [details]
Patch v7

Patches v5 and v6 didn't include the new files... again.
Comment 21 Caspar D. CLA 2011-08-11 03:28:33 EDT
(In reply to comment #19)
> Regarding the efficiency of hashCode() and equals() I was mostly referring to
> the hashCode() method. But I noticed that your equals method differs slightly
> from our "standard" idiom, e.g.,

OK, rewritten to follow the idiom exemplified by CDOBranchImpl.
Comment 22 Caspar D. CLA 2011-08-11 03:29:48 EDT
Created attachment 201294 [details]
Patch v8
Comment 23 Caspar D. CLA 2011-08-11 06:08:49 EDT
Created attachment 201307 [details]
Patch v9

Addressed my own TODOs. I think it's ready now, flagging 
for review again.
Comment 24 Eike Stepper CLA 2011-08-16 07:10:44 EDT
Created attachment 201560 [details]
Patch v10

The patch looks very good and all tests are passing. I approve this patch and take your word that you add JavaDoc to these items before you commit it:

CDOLockOwner
CDOLockUtil
CDOObject.cdoLockState()
CDOLocksChangedEvent
CDOView.Options.isLockNotificationEnabled()
CDOView.Options.setLockNotificationEnabled(boolean)
Comment 25 Caspar D. CLA 2011-08-17 22:27:53 EDT
Committed revision 8908.
Comment 26 Caspar D. CLA 2011-08-18 01:21:22 EDT
Created attachment 201686 [details]
Patch v11 (incremental)

Discovered 2 gross errors:

* While the notifications work, the new lockStates are not actually
  processed locally. The fix for this is a trivial one-liner.

* LockManager.unlock2 updates the persisted lockState before calling
  super.unlock2. But super.unlock2 might fail. The order should be
  the other way around. Here too, the fix is trivial.

I enhanced LockingNotificationsTest and moved the test listener that
was contained there, to o.e.e.cdo.tests.util
Comment 27 Caspar D. CLA 2011-08-18 01:22:10 EDT
Reopening for a review of the additional patch.
Comment 28 Caspar D. CLA 2011-08-18 01:33:54 EDT
Created attachment 201687 [details]
Patch v12 (incremental)

Patched the patch.
Comment 29 Eike Stepper CLA 2011-08-18 01:40:54 EDT
By accident I just found out that there are several public overrides of synchronized super methods that are themselves not synchronized. I mean in org.eclipse.emf.cdo.internal.server.LockManager. Can you please check that?
Comment 30 Eike Stepper CLA 2011-08-18 01:53:08 EDT
Committed revision 8912:
- trunk/plugins/org.eclipse.emf.cdo.tests
Comment 31 Eike Stepper CLA 2011-08-18 02:22:56 EDT
Can you remember why org.eclipse.emf.cdo.tests.offline.OfflineLockingTest.testMasterLocks_ArrivalInClone() is empty?
Comment 32 Eike Stepper CLA 2011-08-18 02:43:35 EDT
Created attachment 201690 [details]
Patch v13 (incremental)

I've synchronized these methods:

LockManager.unlock(boolean, LockType, IView, Collection<? extends Object>)
LockManager.unlock2(boolean, LockType, IView, Collection<? extends Object>)
LockManager.unlock(boolean, IView)
LockManager.unlock2(boolean, IView)
Comment 33 Caspar D. CLA 2011-08-18 03:03:15 EDT
(In reply to comment #31)
> Can you remember why 
> org.eclipse.emf.cdo.tests.offline.OfflineLockingTest.
> testMasterLocks_ArrivalInClone()
> is empty?

I'll implement it as part of Bug 351912.
Comment 34 Caspar D. CLA 2011-08-18 03:11:26 EDT
Committed revision 8915.
Comment 35 Caspar D. CLA 2011-08-18 03:25:35 EDT
(In reply to comment #29)
> By accident I just found out that there are several public overrides of
> synchronized super methods that are themselves not synchronized. I mean in
> org.eclipse.emf.cdo.internal.server.LockManager. Can you please check that?

Which methods? I didn't find any that are unsynced while overriding a
synced method.
Comment 36 Eike Stepper CLA 2011-08-18 03:32:26 EDT
(In reply to comment #35)
> (In reply to comment #29)
> > By accident I just found out that there are several public overrides of
> > synchronized super methods that are themselves not synchronized. I mean in
> > org.eclipse.emf.cdo.internal.server.LockManager. Can you please check that?
> 
> Which methods? I didn't find any that are unsynced while overriding a
> synced method.

The ones from comment 32. I fixed that already in the latest patch!
Comment 37 Eike Stepper CLA 2012-09-21 07:16:45 EDT
Closing.
Comment 38 Eike Stepper CLA 2012-12-30 12:12:46 EST
*** Bug 283274 has been marked as a duplicate of this bug. ***
Comment 39 Eike Stepper CLA 2012-12-30 12:20:58 EST
*** Bug 254696 has been marked as a duplicate of this bug. ***
Comment 40 Eike Stepper CLA 2012-12-31 02:11:47 EST
*** Bug 273411 has been marked as a duplicate of this bug. ***