Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » [CDO] A locked CDOView has objects removed from its model
[CDO] A locked CDOView has objects removed from its model [message #424343] Fri, 24 October 2008 05:22 Go to next message
Stephen McCants is currently offline Stephen McCantsFriend
Messages: 92
Registered: July 2009
Member
Hello,
I'm working with the latest from HEAD now and I'm working with locks on a CDOView. I wrote a
simple test case to see if it is working (as I'm having trouble in my complex junit test). I have a
CDO Model object with has a String (name) and a non-containment reference to a Model object.
In the test, I have two sessions. The “out” or first session has a transaction that makes all the
changes. The “in” or second session has a view that it locked before each change. After the
change, I check to make sure that the View doesn't see updates. Then I unlock the View and check to
make sure it can now see the changes. I suspect the Thread.sleep() calls are unnecessary. Below is
the source code for the test:

// Create configuration
CDOSessionConfiguration configuration = CDOUtil.createSessionConfiguration();
configuration.setLazyPackageRegistry();
configuration.setRepositoryName(CDO.getRepositoryName());
IConnector connector = TCPUtil.getConnector(IPluginContainer.INSTANCE,
InetAddress.getLocalHost().getHostName()); // TODO deactivate connector
configuration.setConnector(connector);

// Open session
CDOSession session1 = configuration.openSession();
CDOSession session2 = configuration.openSession();

CDOTransaction transaction = session1.openTransaction();
Resource outResource = transaction.createResource("/model");
Model model = JunitFactory.eINSTANCE.createModel();
model.setName("Junit");
outResource.getContents().add(model);
transaction.commit();

CDOView view = session2.openView();
Resource inResource = view.getResource("/model");
assertThat(inResource, is(notNullValue()));
assertThat(inResource.getContents().size(), is(1));
Model testModel = (Model) inResource.getContents().get(0);
assertThat(testModel.getName(), is("Junit"));

view.getLock().lock();
model.setName("Locked");
transaction.commit();
Thread.sleep(1000);
assertThat(testModel.getName(), is("Junit"));
view.getLock().unlock();
Thread.sleep(1000);
assertThat(testModel.getName(), is("Locked"));

// Add a sub model and make sure that works.
view.getLock().lock();
Model subModel = JunitFactory.eINSTANCE.createModel();
subModel.setName("another name");
outResource.getContents().add(subModel);
model.setSubModel(subModel);
transaction.commit();
Thread.sleep(1000);
assertThat(testModel.getSubModel(), nullValue());
view.getLock().unlock();
Thread.sleep(1000);
assertThat(testModel.getSubModel(), notNullValue());
assertThat(testModel.getSubModel().getName(), is("another name"));

// Now remove the sub model
view.getLock().lock();
model.setSubModel(null);
outResource.getContents().remove(subModel);
transaction.commit();
Thread.sleep(1000);
assertThat(testModel.getSubModel(), notNullValue());
assertThat(testModel.getSubModel().getName(), is("another name"));
assertThat(inResource.getContents().size(), is(2));

The last assertion fails with:

java.lang.AssertionError: Expected: is <2> got: <1>

In otherwords, the subModel has disappeared from the resource, even though the View is still locked.
I'm actually surprised the .getSubModel() didn't return null, but it didn't. Is this a bug with
the locking, or does the locking only apply to the objects under the resource and not the resource
itself.

Thanks for your help!

Sincerely,
Stephen McCants
Re: [CDO] A locked CDOView has objects removed from its model [message #424352 is a reply to message #424343] Fri, 24 October 2008 11:23 Go to previous messageGo to next message
Simon Mc Duff is currently offline Simon Mc DuffFriend
Messages: 596
Registered: July 2009
Senior Member
Hi Stephan!

I didn't work yet with this feature but I understand why it's behave
like that.

You know that each EObject refer to a CDORevision.
CDOSession cache CDORevision
CDOView cache EObject

CDO invalidate the CDORevision in CDOSession
and after send it to the view.
The view will lock it... and wait ...
But Since EObject in that view refer to the CDORevision in CDOSession...
It is already changed..

I believe locks should be implemented in the CDOSession layer instead of
the view layer.

Will it work for you to lock at the CDOSession layer ?

Yes this is a bugs.

Can you re-open bugzilla
249536: Provide a public view lock to protect clients against remote
invalidation
https://bugs.eclipse.org/bugs/show_bug.cgi?id=249536

Simon

Sorry for the delay to give you an answer.. but here it is 7:22 in the
morning and Eike not available this week !:-)

Stephen McCants wrote:
> Hello,
> I'm working with the latest from HEAD now and I'm working with locks
> on a CDOView. I wrote a simple test case to see if it is working (as
> I'm having trouble in my complex junit test). I have a CDO Model object
> with has a String (name) and a non-containment reference to a Model object.
> In the test, I have two sessions. The “out” or first session has a
> transaction that makes all the changes. The “in” or second session has
> a view that it locked before each change. After the change, I check to
> make sure that the View doesn't see updates. Then I unlock the View and
> check to make sure it can now see the changes. I suspect the
> Thread.sleep() calls are unnecessary. Below is the source code for the
> test:
>
> // Create configuration
> CDOSessionConfiguration configuration =
> CDOUtil.createSessionConfiguration();
> configuration.setLazyPackageRegistry();
> configuration.setRepositoryName(CDO.getRepositoryName());
> IConnector connector =
> TCPUtil.getConnector(IPluginContainer.INSTANCE,
> InetAddress.getLocalHost().getHostName()); // TODO deactivate connector
> configuration.setConnector(connector);
>
> // Open session
> CDOSession session1 = configuration.openSession();
> CDOSession session2 = configuration.openSession();
>
> CDOTransaction transaction = session1.openTransaction();
> Resource outResource = transaction.createResource("/model");
> Model model = JunitFactory.eINSTANCE.createModel();
> model.setName("Junit");
> outResource.getContents().add(model);
> transaction.commit();
>
> CDOView view = session2.openView();
> Resource inResource = view.getResource("/model");
> assertThat(inResource, is(notNullValue()));
> assertThat(inResource.getContents().size(), is(1));
> Model testModel = (Model) inResource.getContents().get(0);
> assertThat(testModel.getName(), is("Junit"));
>
> view.getLock().lock();
> model.setName("Locked");
> transaction.commit();
> Thread.sleep(1000);
> assertThat(testModel.getName(), is("Junit"));
> view.getLock().unlock();
> Thread.sleep(1000);
> assertThat(testModel.getName(), is("Locked"));
>
> // Add a sub model and make sure that works.
> view.getLock().lock();
> Model subModel = JunitFactory.eINSTANCE.createModel();
> subModel.setName("another name");
> outResource.getContents().add(subModel);
> model.setSubModel(subModel);
> transaction.commit();
> Thread.sleep(1000);
> assertThat(testModel.getSubModel(), nullValue());
> view.getLock().unlock();
> Thread.sleep(1000);
> assertThat(testModel.getSubModel(), notNullValue());
> assertThat(testModel.getSubModel().getName(), is("another name"));
>
> // Now remove the sub model
> view.getLock().lock();
> model.setSubModel(null);
> outResource.getContents().remove(subModel);
> transaction.commit();
> Thread.sleep(1000);
> assertThat(testModel.getSubModel(), notNullValue());
> assertThat(testModel.getSubModel().getName(), is("another name"));
> assertThat(inResource.getContents().size(), is(2));
>
> The last assertion fails with:
>
> java.lang.AssertionError: Expected: is <2> got: <1>
>
> In otherwords, the subModel has disappeared from the resource, even
> though the View is still locked. I'm actually surprised the
> .getSubModel() didn't return null, but it didn't. Is this a bug with
> the locking, or does the locking only apply to the objects under the
> resource and not the resource itself.
>
> Thanks for your help!
>
> Sincerely,
> Stephen McCants
Re: [CDO] A locked CDOView has objects removed from its model [message #424353 is a reply to message #424352] Fri, 24 October 2008 11:41 Go to previous messageGo to next message
Simon Mc Duff is currently offline Simon Mc DuffFriend
Messages: 596
Registered: July 2009
Senior Member
Just realized something (I'm not awake yet!! :-)

The state of the object is kept in EObject!!! It is not a bugs.

WHen you did the following commit:
>> // Add a sub model and make sure that works.
>> view.getLock().lock();
>> Model subModel = JunitFactory.eINSTANCE.createModel();
>> subModel.setName("another name");
>> outResource.getContents().add(subModel);
>> model.setSubModel(subModel);
>> transaction.commit();
>> Thread.sleep(1000);
>> assertThat(testModel.getSubModel(), nullValue());
>> view.getLock().unlock();
// RESOURCE IS NOW PROXY STATE

You didn't access the inResource object. SO it won't be resolve.
>> // Now remove the sub model
>> view.getLock().lock();
>> model.setSubModel(null);
>> outResource.getContents().remove(subModel);
>> transaction.commit();
>> Thread.sleep(1000);
>> assertThat(testModel.getSubModel(), notNullValue());
>> assertThat(inResource.getContents().size(), is(2)); << RESOLVE
THERE!!

The lock will lock object to not change if they are clean.
It will not lock proxy object... cannot.
You should do the following to make your test work.

view.getLock().unlock();
>> Thread.sleep(1000);
>> assertThat(testModel.getSubModel(), notNullValue());
>> assertThat(testModel.getSubModel().getName(), is("another name"));
inResource.getContents().size()
>>
>> // Now remove the sub model
>> view.getLock().lock();
>> model.setSubModel(null);
>> outResource.getContents().remove(subModel);
>> transaction.commit();
access your at the same

It will change resource state from PROXY to CLEAN.. and now will not
changed.


Basically the rules is the following:
CDOView.lock ONLY locks object that are clean (already accessed). DOes
it make sense ?



Simon McDuff wrote:
> Hi Stephan!
>
> I didn't work yet with this feature but I understand why it's behave
> like that.
>
> You know that each EObject refer to a CDORevision.
> CDOSession cache CDORevision
> CDOView cache EObject
>
> CDO invalidate the CDORevision in CDOSession
> and after send it to the view.
> The view will lock it... and wait ...
> But Since EObject in that view refer to the CDORevision in CDOSession...
> It is already changed..
>
> I believe locks should be implemented in the CDOSession layer instead of
> the view layer.
>
> Will it work for you to lock at the CDOSession layer ?
>
> Yes this is a bugs.
>
> Can you re-open bugzilla
> 249536: Provide a public view lock to protect clients against remote
> invalidation
> https://bugs.eclipse.org/bugs/show_bug.cgi?id=249536
>
> Simon
>
> Sorry for the delay to give you an answer.. but here it is 7:22 in the
> morning and Eike not available this week !:-)
>
> Stephen McCants wrote:
>> Hello,
>> I'm working with the latest from HEAD now and I'm working with
>> locks on a CDOView. I wrote a simple test case to see if it is
>> working (as I'm having trouble in my complex junit test). I have a
>> CDO Model object with has a String (name) and a non-containment
>> reference to a Model object.
>> In the test, I have two sessions. The “out” or first session has
>> a transaction that makes all the changes. The “in” or second session
>> has a view that it locked before each change. After the change, I
>> check to make sure that the View doesn't see updates. Then I unlock
>> the View and check to make sure it can now see the changes. I suspect
>> the Thread.sleep() calls are unnecessary. Below is the source code
>> for the test:
>>
>> // Create configuration
>> CDOSessionConfiguration configuration =
>> CDOUtil.createSessionConfiguration();
>> configuration.setLazyPackageRegistry();
>> configuration.setRepositoryName(CDO.getRepositoryName());
>> IConnector connector =
>> TCPUtil.getConnector(IPluginContainer.INSTANCE,
>> InetAddress.getLocalHost().getHostName()); // TODO deactivate connector
>> configuration.setConnector(connector);
>>
>> // Open session
>> CDOSession session1 = configuration.openSession();
>> CDOSession session2 = configuration.openSession();
>>
>> CDOTransaction transaction = session1.openTransaction();
>> Resource outResource = transaction.createResource("/model");
>> Model model = JunitFactory.eINSTANCE.createModel();
>> model.setName("Junit");
>> outResource.getContents().add(model);
>> transaction.commit();
>>
>> CDOView view = session2.openView();
>> Resource inResource = view.getResource("/model");
>> assertThat(inResource, is(notNullValue()));
>> assertThat(inResource.getContents().size(), is(1));
>> Model testModel = (Model) inResource.getContents().get(0);
>> assertThat(testModel.getName(), is("Junit"));
>>
>> view.getLock().lock();
>> model.setName("Locked");
>> transaction.commit();
>> Thread.sleep(1000);
>> assertThat(testModel.getName(), is("Junit"));
>> view.getLock().unlock();
>> Thread.sleep(1000);
>> assertThat(testModel.getName(), is("Locked"));
>>
>> // Add a sub model and make sure that works.
>> view.getLock().lock();
>> Model subModel = JunitFactory.eINSTANCE.createModel();
>> subModel.setName("another name");
>> outResource.getContents().add(subModel);
>> model.setSubModel(subModel);
>> transaction.commit();
>> Thread.sleep(1000);
>> assertThat(testModel.getSubModel(), nullValue());
>> view.getLock().unlock();
>> Thread.sleep(1000);
>> assertThat(testModel.getSubModel(), notNullValue());
>> assertThat(testModel.getSubModel().getName(), is("another name"));
>>
>> // Now remove the sub model
>> view.getLock().lock();
>> model.setSubModel(null);
>> outResource.getContents().remove(subModel);
>> transaction.commit();
>> Thread.sleep(1000);
>> assertThat(testModel.getSubModel(), notNullValue());
>> assertThat(testModel.getSubModel().getName(), is("another name"));
>> assertThat(inResource.getContents().size(), is(2));
>>
>> The last assertion fails with:
>>
>> java.lang.AssertionError: Expected: is <2> got: <1>
>>
>> In otherwords, the subModel has disappeared from the resource, even
>> though the View is still locked. I'm actually surprised the
>> .getSubModel() didn't return null, but it didn't. Is this a bug with
>> the locking, or does the locking only apply to the objects under the
>> resource and not the resource itself.
>>
>> Thanks for your help!
>>
>> Sincerely,
>> Stephen McCants
Re: [CDO] A locked CDOView has objects removed from its model [message #424363 is a reply to message #424343] Fri, 24 October 2008 15:06 Go to previous messageGo to next message
Eike Stepper is currently offline Eike StepperFriend
Messages: 6682
Registered: July 2009
Senior Member
Hi Stephen,

As Simon said, I'm not "so" available this week ;-)
So I didn't have the time to really think about this issue.
But it strikes me that , at least in productive code, you should ensure
the *unlocking* of the view in a finally clause of a try block.

More next week when I'm back home...

Cheers
/Eike



Stephen McCants schrieb:
> Hello,
> I'm working with the latest from HEAD now and I'm working with
> locks on a CDOView. I wrote a simple test case to see if it is
> working (as I'm having trouble in my complex junit test). I have a
> CDO Model object with has a String (name) and a non-containment
> reference to a Model object.
> In the test, I have two sessions. The “out” or first session has
> a transaction that makes all the changes. The “in” or second session
> has a view that it locked before each change. After the change, I
> check to make sure that the View doesn't see updates. Then I unlock
> the View and check to make sure it can now see the changes. I suspect
> the Thread.sleep() calls are unnecessary. Below is the source code
> for the test:
>
> // Create configuration
> CDOSessionConfiguration configuration =
> CDOUtil.createSessionConfiguration();
> configuration.setLazyPackageRegistry();
> configuration.setRepositoryName(CDO.getRepositoryName());
> IConnector connector =
> TCPUtil.getConnector(IPluginContainer.INSTANCE,
> InetAddress.getLocalHost().getHostName()); // TODO deactivate connector
> configuration.setConnector(connector);
>
> // Open session
> CDOSession session1 = configuration.openSession();
> CDOSession session2 = configuration.openSession();
>
> CDOTransaction transaction = session1.openTransaction();
> Resource outResource = transaction.createResource("/model");
> Model model = JunitFactory.eINSTANCE.createModel();
> model.setName("Junit");
> outResource.getContents().add(model);
> transaction.commit();
>
> CDOView view = session2.openView();
> Resource inResource = view.getResource("/model");
> assertThat(inResource, is(notNullValue()));
> assertThat(inResource.getContents().size(), is(1));
> Model testModel = (Model) inResource.getContents().get(0);
> assertThat(testModel.getName(), is("Junit"));
>
> view.getLock().lock();
> model.setName("Locked");
> transaction.commit();
> Thread.sleep(1000);
> assertThat(testModel.getName(), is("Junit"));
> view.getLock().unlock();
> Thread.sleep(1000);
> assertThat(testModel.getName(), is("Locked"));
>
> // Add a sub model and make sure that works.
> view.getLock().lock();
> Model subModel = JunitFactory.eINSTANCE.createModel();
> subModel.setName("another name");
> outResource.getContents().add(subModel);
> model.setSubModel(subModel);
> transaction.commit();
> Thread.sleep(1000);
> assertThat(testModel.getSubModel(), nullValue());
> view.getLock().unlock();
> Thread.sleep(1000);
> assertThat(testModel.getSubModel(), notNullValue());
> assertThat(testModel.getSubModel().getName(), is("another name"));
>
> // Now remove the sub model
> view.getLock().lock();
> model.setSubModel(null);
> outResource.getContents().remove(subModel);
> transaction.commit();
> Thread.sleep(1000);
> assertThat(testModel.getSubModel(), notNullValue());
> assertThat(testModel.getSubModel().getName(), is("another name"));
> assertThat(inResource.getContents().size(), is(2));
>
> The last assertion fails with:
>
> java.lang.AssertionError: Expected: is <2> got: <1>
>
> In otherwords, the subModel has disappeared from the resource, even
> though the View is still locked. I'm actually surprised the
> .getSubModel() didn't return null, but it didn't. Is this a bug with
> the locking, or does the locking only apply to the objects under the
> resource and not the resource itself.
>
> Thanks for your help!
>
> Sincerely,
> Stephen McCants


Re: [CDO] A locked CDOView has objects removed from its model [message #424365 is a reply to message #424353] Fri, 24 October 2008 16:04 Go to previous messageGo to next message
Stephen McCants is currently offline Stephen McCantsFriend
Messages: 92
Registered: July 2009
Member
Hi Simon,
Okay, I think I understand this and it makes sense. The View can only lock objects that it has
(i.e. objects in the CLEAN state) and cannot lock object that it hasn't loaded (i.e. objects in the
PROXY state).
That makes sense to me, but I think there can be subtle problems. Let's consider a CDO model with
ObjectA (rev 1) and ObjectB (rev 1) in it. A View is locked and loads ObjectA (rev 1). Now a
separate transaction changes ObjectA and ObjectB and commits the change which sets them to "rev 2".
The locked View will see ObjectA (rev 1) still, but if it loads ObjectB after the commit, then it
will get ObjectB (rev 2). In that case it would be seeing a model that is potentially inconsistent
and has half of a committed transaction. That could be bad.
Am I thinking correctly about this?
It seems that the only way (currently) to ensure that you have a consistent model is to use audits.
Is that true as well?

Thanks for your help!

Sincerely,
Stephen McCants

Simon McDuff wrote:
> Just realized something (I'm not awake yet!! :-)
>
> The state of the object is kept in EObject!!! It is not a bugs.
>
> WHen you did the following commit:
> >> // Add a sub model and make sure that works.
> >> view.getLock().lock();
> >> Model subModel = JunitFactory.eINSTANCE.createModel();
> >> subModel.setName("another name");
> >> outResource.getContents().add(subModel);
> >> model.setSubModel(subModel);
> >> transaction.commit();
> >> Thread.sleep(1000);
> >> assertThat(testModel.getSubModel(), nullValue());
> >> view.getLock().unlock();
> // RESOURCE IS NOW PROXY STATE
>
> You didn't access the inResource object. SO it won't be resolve.
> >> // Now remove the sub model
> >> view.getLock().lock();
> >> model.setSubModel(null);
> >> outResource.getContents().remove(subModel);
> >> transaction.commit();
> >> Thread.sleep(1000);
> >> assertThat(testModel.getSubModel(), notNullValue());
> >> assertThat(inResource.getContents().size(), is(2)); << RESOLVE
> THERE!!
>
> The lock will lock object to not change if they are clean.
> It will not lock proxy object... cannot.
> You should do the following to make your test work.
>
> view.getLock().unlock();
> >> Thread.sleep(1000);
> >> assertThat(testModel.getSubModel(), notNullValue());
> >> assertThat(testModel.getSubModel().getName(), is("another name"));
> inResource.getContents().size()
> >>
> >> // Now remove the sub model
> >> view.getLock().lock();
> >> model.setSubModel(null);
> >> outResource.getContents().remove(subModel);
> >> transaction.commit();
> access your at the same
>
> It will change resource state from PROXY to CLEAN.. and now will not
> changed.
>
>
> Basically the rules is the following:
> CDOView.lock ONLY locks object that are clean (already accessed). DOes
> it make sense ?
>
>
>
> Simon McDuff wrote:
>> Hi Stephan!
>>
>> I didn't work yet with this feature but I understand why it's behave
>> like that.
>>
>> You know that each EObject refer to a CDORevision.
>> CDOSession cache CDORevision
>> CDOView cache EObject
>>
>> CDO invalidate the CDORevision in CDOSession
>> and after send it to the view.
>> The view will lock it... and wait ...
>> But Since EObject in that view refer to the CDORevision in
>> CDOSession... It is already changed..
>>
>> I believe locks should be implemented in the CDOSession layer instead
>> of the view layer.
>>
>> Will it work for you to lock at the CDOSession layer ?
>>
>> Yes this is a bugs.
>>
>> Can you re-open bugzilla
>> 249536: Provide a public view lock to protect clients against remote
>> invalidation
>> https://bugs.eclipse.org/bugs/show_bug.cgi?id=249536
>>
>> Simon
>>
>> Sorry for the delay to give you an answer.. but here it is 7:22 in the
>> morning and Eike not available this week !:-)
>>
>> Stephen McCants wrote:
>>> Hello,
>>> I'm working with the latest from HEAD now and I'm working with
>>> locks on a CDOView. I wrote a simple test case to see if it is
>>> working (as I'm having trouble in my complex junit test). I have a
>>> CDO Model object with has a String (name) and a non-containment
>>> reference to a Model object.
>>> In the test, I have two sessions. The “out” or first session has
>>> a transaction that makes all the changes. The “in” or second session
>>> has a view that it locked before each change. After the change, I
>>> check to make sure that the View doesn't see updates. Then I unlock
>>> the View and check to make sure it can now see the changes. I
>>> suspect the Thread.sleep() calls are unnecessary. Below is the
>>> source code for the test:
>>>
>>> // Create configuration
>>> CDOSessionConfiguration configuration =
>>> CDOUtil.createSessionConfiguration();
>>> configuration.setLazyPackageRegistry();
>>> configuration.setRepositoryName(CDO.getRepositoryName());
>>> IConnector connector =
>>> TCPUtil.getConnector(IPluginContainer.INSTANCE,
>>> InetAddress.getLocalHost().getHostName()); // TODO deactivate connector
>>> configuration.setConnector(connector);
>>>
>>> // Open session
>>> CDOSession session1 = configuration.openSession();
>>> CDOSession session2 = configuration.openSession();
>>>
>>> CDOTransaction transaction = session1.openTransaction();
>>> Resource outResource = transaction.createResource("/model");
>>> Model model = JunitFactory.eINSTANCE.createModel();
>>> model.setName("Junit");
>>> outResource.getContents().add(model);
>>> transaction.commit();
>>>
>>> CDOView view = session2.openView();
>>> Resource inResource = view.getResource("/model");
>>> assertThat(inResource, is(notNullValue()));
>>> assertThat(inResource.getContents().size(), is(1));
>>> Model testModel = (Model) inResource.getContents().get(0);
>>> assertThat(testModel.getName(), is("Junit"));
>>>
>>> view.getLock().lock();
>>> model.setName("Locked");
>>> transaction.commit();
>>> Thread.sleep(1000);
>>> assertThat(testModel.getName(), is("Junit"));
>>> view.getLock().unlock();
>>> Thread.sleep(1000);
>>> assertThat(testModel.getName(), is("Locked"));
>>>
>>> // Add a sub model and make sure that works.
>>> view.getLock().lock();
>>> Model subModel = JunitFactory.eINSTANCE.createModel();
>>> subModel.setName("another name");
>>> outResource.getContents().add(subModel);
>>> model.setSubModel(subModel);
>>> transaction.commit();
>>> Thread.sleep(1000);
>>> assertThat(testModel.getSubModel(), nullValue());
>>> view.getLock().unlock();
>>> Thread.sleep(1000);
>>> assertThat(testModel.getSubModel(), notNullValue());
>>> assertThat(testModel.getSubModel().getName(), is("another name"));
>>>
>>> // Now remove the sub model
>>> view.getLock().lock();
>>> model.setSubModel(null);
>>> outResource.getContents().remove(subModel);
>>> transaction.commit();
>>> Thread.sleep(1000);
>>> assertThat(testModel.getSubModel(), notNullValue());
>>> assertThat(testModel.getSubModel().getName(), is("another name"));
>>> assertThat(inResource.getContents().size(), is(2));
>>>
>>> The last assertion fails with:
>>>
>>> java.lang.AssertionError: Expected: is <2> got: <1>
>>>
>>> In otherwords, the subModel has disappeared from the resource, even
>>> though the View is still locked. I'm actually surprised the
>>> .getSubModel() didn't return null, but it didn't. Is this a bug with
>>> the locking, or does the locking only apply to the objects under the
>>> resource and not the resource itself.
>>>
>>> Thanks for your help!
>>>
>>> Sincerely,
>>> Stephen McCants
Re: [CDO] A locked CDOView has objects removed from its model [message #424366 is a reply to message #424363] Fri, 24 October 2008 16:06 Go to previous messageGo to next message
Stephen McCants is currently offline Stephen McCantsFriend
Messages: 92
Registered: July 2009
Member
Hi Eike,
You are, of course, correct. I left the try/finally blocks out to make the code easier to read and
I will certainly use them in the production code to avoid deadlocking.
Thanks!
--Stephen

Eike Stepper wrote:
> Hi Stephen,
>
> As Simon said, I'm not "so" available this week ;-)
> So I didn't have the time to really think about this issue.
> But it strikes me that , at least in productive code, you should ensure
> the *unlocking* of the view in a finally clause of a try block.
>
> More next week when I'm back home...
>
> Cheers
> /Eike
Re: [CDO] A locked CDOView has objects removed from its model [message #424367 is a reply to message #424365] Fri, 24 October 2008 17:06 Go to previous messageGo to next message
Simon Mc Duff is currently offline Simon Mc DuffFriend
Messages: 596
Registered: July 2009
Senior Member
Stephen McCants wrote:
> Hi Simon,
> Okay, I think I understand this and it makes sense. The View can
> only lock objects that it has (i.e. objects in the CLEAN state) and
> cannot lock object that it hasn't loaded (i.e. objects in the PROXY state).
> That makes sense to me, but I think there can be subtle problems.
> Let's consider a CDO model with ObjectA (rev 1) and ObjectB (rev 1) in
> it. A View is locked and loads ObjectA (rev 1). Now a separate
> transaction changes ObjectA and ObjectB and commits the change which
> sets them to "rev 2". The locked View will see ObjectA (rev 1) still,
> but if it loads ObjectB after the commit, then it will get ObjectB (rev
> 2). In that case it would be seeing a model that is potentially
> inconsistent and has half of a committed transaction. That could be bad.
> Am I thinking correctly about this?
You are thinking correctly.
But this feature was not intended to block all call for all objects.

> It seems that the only way (currently) to ensure that you have a
> consistent model is to use audits. Is that true as well?
No. You can use on the

session.setPassiveUpdateEnabled(false);

you can refresh your session by calling

session.refresh();

You will not receive any updates!

See the
http://wiki.eclipse.org/New_And_Noteworthy_for_CDO_2.0#Make_ remote_invalidation_configurable

Simon

>
> Thanks for your help!
>
> Sincerely,
> Stephen McCants
>
> Simon McDuff wrote:
>> Just realized something (I'm not awake yet!! :-)
>>
>> The state of the object is kept in EObject!!! It is not a bugs.
>>
>> WHen you did the following commit:
>> >> // Add a sub model and make sure that works.
>> >> view.getLock().lock();
>> >> Model subModel = JunitFactory.eINSTANCE.createModel();
>> >> subModel.setName("another name");
>> >> outResource.getContents().add(subModel);
>> >> model.setSubModel(subModel);
>> >> transaction.commit();
>> >> Thread.sleep(1000);
>> >> assertThat(testModel.getSubModel(), nullValue());
>> >> view.getLock().unlock();
>> // RESOURCE IS NOW PROXY STATE
>>
>> You didn't access the inResource object. SO it won't be resolve.
>> >> // Now remove the sub model
>> >> view.getLock().lock();
>> >> model.setSubModel(null);
>> >> outResource.getContents().remove(subModel);
>> >> transaction.commit();
>> >> Thread.sleep(1000);
>> >> assertThat(testModel.getSubModel(), notNullValue());
>> >> assertThat(inResource.getContents().size(), is(2)); <<
>> RESOLVE THERE!!
>>
>> The lock will lock object to not change if they are clean.
>> It will not lock proxy object... cannot.
>> You should do the following to make your test work.
>>
>> view.getLock().unlock();
>> >> Thread.sleep(1000);
>> >> assertThat(testModel.getSubModel(), notNullValue());
>> >> assertThat(testModel.getSubModel().getName(), is("another
>> name"));
>> inResource.getContents().size()
>> >>
>> >> // Now remove the sub model
>> >> view.getLock().lock();
>> >> model.setSubModel(null);
>> >> outResource.getContents().remove(subModel);
>> >> transaction.commit();
>> access your at the same
>>
>> It will change resource state from PROXY to CLEAN.. and now will not
>> changed.
>>
>>
>> Basically the rules is the following:
>> CDOView.lock ONLY locks object that are clean (already accessed). DOes
>> it make sense ?
>>
>>
>>
>> Simon McDuff wrote:
>>> Hi Stephan!
>>>
>>> I didn't work yet with this feature but I understand why it's behave
>>> like that.
>>>
>>> You know that each EObject refer to a CDORevision.
>>> CDOSession cache CDORevision
>>> CDOView cache EObject
>>>
>>> CDO invalidate the CDORevision in CDOSession
>>> and after send it to the view.
>>> The view will lock it... and wait ...
>>> But Since EObject in that view refer to the CDORevision in
>>> CDOSession... It is already changed..
>>>
>>> I believe locks should be implemented in the CDOSession layer instead
>>> of the view layer.
>>>
>>> Will it work for you to lock at the CDOSession layer ?
>>>
>>> Yes this is a bugs.
>>>
>>> Can you re-open bugzilla
>>> 249536: Provide a public view lock to protect clients against remote
>>> invalidation
>>> https://bugs.eclipse.org/bugs/show_bug.cgi?id=249536
>>>
>>> Simon
>>>
>>> Sorry for the delay to give you an answer.. but here it is 7:22 in
>>> the morning and Eike not available this week !:-)
>>>
>>> Stephen McCants wrote:
>>>> Hello,
>>>> I'm working with the latest from HEAD now and I'm working with
>>>> locks on a CDOView. I wrote a simple test case to see if it is
>>>> working (as I'm having trouble in my complex junit test). I have a
>>>> CDO Model object with has a String (name) and a non-containment
>>>> reference to a Model object.
>>>> In the test, I have two sessions. The “out” or first session
>>>> has a transaction that makes all the changes. The “in” or second
>>>> session has a view that it locked before each change. After the
>>>> change, I check to make sure that the View doesn't see updates.
>>>> Then I unlock the View and check to make sure it can now see the
>>>> changes. I suspect the Thread.sleep() calls are unnecessary. Below
>>>> is the source code for the test:
>>>>
>>>> // Create configuration
>>>> CDOSessionConfiguration configuration =
>>>> CDOUtil.createSessionConfiguration();
>>>> configuration.setLazyPackageRegistry();
>>>> configuration.setRepositoryName(CDO.getRepositoryName());
>>>> IConnector connector =
>>>> TCPUtil.getConnector(IPluginContainer.INSTANCE,
>>>> InetAddress.getLocalHost().getHostName()); // TODO deactivate connector
>>>> configuration.setConnector(connector);
>>>>
>>>> // Open session
>>>> CDOSession session1 = configuration.openSession();
>>>> CDOSession session2 = configuration.openSession();
>>>>
>>>> CDOTransaction transaction = session1.openTransaction();
>>>> Resource outResource = transaction.createResource("/model");
>>>> Model model = JunitFactory.eINSTANCE.createModel();
>>>> model.setName("Junit");
>>>> outResource.getContents().add(model);
>>>> transaction.commit();
>>>>
>>>> CDOView view = session2.openView();
>>>> Resource inResource = view.getResource("/model");
>>>> assertThat(inResource, is(notNullValue()));
>>>> assertThat(inResource.getContents().size(), is(1));
>>>> Model testModel = (Model) inResource.getContents().get(0);
>>>> assertThat(testModel.getName(), is("Junit"));
>>>>
>>>> view.getLock().lock();
>>>> model.setName("Locked");
>>>> transaction.commit();
>>>> Thread.sleep(1000);
>>>> assertThat(testModel.getName(), is("Junit"));
>>>> view.getLock().unlock();
>>>> Thread.sleep(1000);
>>>> assertThat(testModel.getName(), is("Locked"));
>>>>
>>>> // Add a sub model and make sure that works.
>>>> view.getLock().lock();
>>>> Model subModel = JunitFactory.eINSTANCE.createModel();
>>>> subModel.setName("another name");
>>>> outResource.getContents().add(subModel);
>>>> model.setSubModel(subModel);
>>>> transaction.commit();
>>>> Thread.sleep(1000);
>>>> assertThat(testModel.getSubModel(), nullValue());
>>>> view.getLock().unlock();
>>>> Thread.sleep(1000);
>>>> assertThat(testModel.getSubModel(), notNullValue());
>>>> assertThat(testModel.getSubModel().getName(), is("another name"));
>>>>
>>>> // Now remove the sub model
>>>> view.getLock().lock();
>>>> model.setSubModel(null);
>>>> outResource.getContents().remove(subModel);
>>>> transaction.commit();
>>>> Thread.sleep(1000);
>>>> assertThat(testModel.getSubModel(), notNullValue());
>>>> assertThat(testModel.getSubModel().getName(), is("another name"));
>>>> assertThat(inResource.getContents().size(), is(2));
>>>>
>>>> The last assertion fails with:
>>>>
>>>> java.lang.AssertionError: Expected: is <2> got: <1>
>>>>
>>>> In otherwords, the subModel has disappeared from the resource, even
>>>> though the View is still locked. I'm actually surprised the
>>>> .getSubModel() didn't return null, but it didn't. Is this a bug
>>>> with the locking, or does the locking only apply to the objects
>>>> under the resource and not the resource itself.
>>>>
>>>> Thanks for your help!
>>>>
>>>> Sincerely,
>>>> Stephen McCants
Re: [CDO] A locked CDOView has objects removed from its model [message #424437 is a reply to message #424365] Sun, 26 October 2008 12:40 Go to previous messageGo to next message
Eike Stepper is currently offline Eike StepperFriend
Messages: 6682
Registered: July 2009
Senior Member
Stephen,

Comments below...



Stephen McCants schrieb:
> Hi Simon,
> Okay, I think I understand this and it makes sense. The View can
> only lock objects that it has (i.e. objects in the CLEAN state) and
> cannot lock object that it hasn't loaded (i.e. objects in the PROXY
> state).
> That makes sense to me, but I think there can be subtle problems.
> Let's consider a CDO model with ObjectA (rev 1) and ObjectB (rev 1) in
> it. A View is locked and loads ObjectA (rev 1). Now a separate
> transaction changes ObjectA and ObjectB and commits the change which
> sets them to "rev 2". The locked View will see ObjectA (rev 1) still,
> but if it loads ObjectB after the commit, then it will get ObjectB
> (rev 2). In that case it would be seeing a model that is potentially
> inconsistent and has half of a committed transaction.
Locking a CDOView means to block the background thread that processes
the remote change notifications from "invalidating" the objects in the
view. As soon as you unlock the view the blocked notifications are
processed and the objects invalidated. Such change notifications always
contain the information about all objects that were changed in a remote
transaction. Depending on whether you are currently holding the view
lock or not either all changed objects are invalidated or none of them
(until you release the lock).

I would say that the usage of the view lock can not lead to inconcistent
data being visible. Or dou you mean something else?


> That could be bad.
> Am I thinking correctly about this?
> It seems that the only way (currently) to ensure that you have a
> consistent model is to use audits. Is that true as well?
No there's the possibility to (temporarily) switch off all passive
updates. I think Simon gave some explanation already.

Cheers
/Eike


>
> Thanks for your help!
>
> Sincerely,
> Stephen McCants
>
> Simon McDuff wrote:
>> Just realized something (I'm not awake yet!! :-)
>>
>> The state of the object is kept in EObject!!! It is not a bugs.
>>
>> WHen you did the following commit:
>> >> // Add a sub model and make sure that works.
>> >> view.getLock().lock();
>> >> Model subModel = JunitFactory.eINSTANCE.createModel();
>> >> subModel.setName("another name");
>> >> outResource.getContents().add(subModel);
>> >> model.setSubModel(subModel);
>> >> transaction.commit();
>> >> Thread.sleep(1000);
>> >> assertThat(testModel.getSubModel(), nullValue());
>> >> view.getLock().unlock();
>> // RESOURCE IS NOW PROXY STATE
>>
>> You didn't access the inResource object. SO it won't be resolve.
>> >> // Now remove the sub model
>> >> view.getLock().lock();
>> >> model.setSubModel(null);
>> >> outResource.getContents().remove(subModel);
>> >> transaction.commit();
>> >> Thread.sleep(1000);
>> >> assertThat(testModel.getSubModel(), notNullValue());
>> >> assertThat(inResource.getContents().size(), is(2)); <<
>> RESOLVE THERE!!
>>
>> The lock will lock object to not change if they are clean.
>> It will not lock proxy object... cannot.
>> You should do the following to make your test work.
>>
>> view.getLock().unlock();
>> >> Thread.sleep(1000);
>> >> assertThat(testModel.getSubModel(), notNullValue());
>> >> assertThat(testModel.getSubModel().getName(), is("another
>> name"));
>> inResource.getContents().size()
>> >>
>> >> // Now remove the sub model
>> >> view.getLock().lock();
>> >> model.setSubModel(null);
>> >> outResource.getContents().remove(subModel);
>> >> transaction.commit();
>> access your at the same
>>
>> It will change resource state from PROXY to CLEAN.. and now will not
>> changed.
>>
>>
>> Basically the rules is the following:
>> CDOView.lock ONLY locks object that are clean (already accessed).
>> DOes it make sense ?
>>
>>
>>
>> Simon McDuff wrote:
>>> Hi Stephan!
>>>
>>> I didn't work yet with this feature but I understand why it's behave
>>> like that.
>>>
>>> You know that each EObject refer to a CDORevision.
>>> CDOSession cache CDORevision
>>> CDOView cache EObject
>>>
>>> CDO invalidate the CDORevision in CDOSession
>>> and after send it to the view.
>>> The view will lock it... and wait ...
>>> But Since EObject in that view refer to the CDORevision in
>>> CDOSession... It is already changed..
>>>
>>> I believe locks should be implemented in the CDOSession layer
>>> instead of the view layer.
>>>
>>> Will it work for you to lock at the CDOSession layer ?
>>>
>>> Yes this is a bugs.
>>>
>>> Can you re-open bugzilla
>>> 249536: Provide a public view lock to protect clients against remote
>>> invalidation
>>> https://bugs.eclipse.org/bugs/show_bug.cgi?id=249536
>>>
>>> Simon
>>>
>>> Sorry for the delay to give you an answer.. but here it is 7:22 in
>>> the morning and Eike not available this week !:-)
>>>
>>> Stephen McCants wrote:
>>>> Hello,
>>>> I'm working with the latest from HEAD now and I'm working with
>>>> locks on a CDOView. I wrote a simple test case to see if it is
>>>> working (as I'm having trouble in my complex junit test). I have a
>>>> CDO Model object with has a String (name) and a non-containment
>>>> reference to a Model object.
>>>> In the test, I have two sessions. The “out” or first session
>>>> has a transaction that makes all the changes. The “in” or second
>>>> session has a view that it locked before each change. After the
>>>> change, I check to make sure that the View doesn't see updates.
>>>> Then I unlock the View and check to make sure it can now see the
>>>> changes. I suspect the Thread.sleep() calls are unnecessary.
>>>> Below is the source code for the test:
>>>>
>>>> // Create configuration
>>>> CDOSessionConfiguration configuration =
>>>> CDOUtil.createSessionConfiguration();
>>>> configuration.setLazyPackageRegistry();
>>>> configuration.setRepositoryName(CDO.getRepositoryName());
>>>> IConnector connector =
>>>> TCPUtil.getConnector(IPluginContainer.INSTANCE,
>>>> InetAddress.getLocalHost().getHostName()); // TODO deactivate
>>>> connector
>>>> configuration.setConnector(connector);
>>>>
>>>> // Open session
>>>> CDOSession session1 = configuration.openSession();
>>>> CDOSession session2 = configuration.openSession();
>>>>
>>>> CDOTransaction transaction = session1.openTransaction();
>>>> Resource outResource = transaction.createResource("/model");
>>>> Model model = JunitFactory.eINSTANCE.createModel();
>>>> model.setName("Junit");
>>>> outResource.getContents().add(model);
>>>> transaction.commit();
>>>>
>>>> CDOView view = session2.openView();
>>>> Resource inResource = view.getResource("/model");
>>>> assertThat(inResource, is(notNullValue()));
>>>> assertThat(inResource.getContents().size(), is(1));
>>>> Model testModel = (Model) inResource.getContents().get(0);
>>>> assertThat(testModel.getName(), is("Junit"));
>>>>
>>>> view.getLock().lock();
>>>> model.setName("Locked");
>>>> transaction.commit();
>>>> Thread.sleep(1000);
>>>> assertThat(testModel.getName(), is("Junit"));
>>>> view.getLock().unlock();
>>>> Thread.sleep(1000);
>>>> assertThat(testModel.getName(), is("Locked"));
>>>>
>>>> // Add a sub model and make sure that works.
>>>> view.getLock().lock();
>>>> Model subModel = JunitFactory.eINSTANCE.createModel();
>>>> subModel.setName("another name");
>>>> outResource.getContents().add(subModel);
>>>> model.setSubModel(subModel);
>>>> transaction.commit();
>>>> Thread.sleep(1000);
>>>> assertThat(testModel.getSubModel(), nullValue());
>>>> view.getLock().unlock();
>>>> Thread.sleep(1000);
>>>> assertThat(testModel.getSubModel(), notNullValue());
>>>> assertThat(testModel.getSubModel().getName(), is("another name"));
>>>>
>>>> // Now remove the sub model
>>>> view.getLock().lock();
>>>> model.setSubModel(null);
>>>> outResource.getContents().remove(subModel);
>>>> transaction.commit();
>>>> Thread.sleep(1000);
>>>> assertThat(testModel.getSubModel(), notNullValue());
>>>> assertThat(testModel.getSubModel().getName(), is("another name"));
>>>> assertThat(inResource.getContents().size(), is(2));
>>>>
>>>> The last assertion fails with:
>>>>
>>>> java.lang.AssertionError: Expected: is <2> got: <1>
>>>>
>>>> In otherwords, the subModel has disappeared from the resource, even
>>>> though the View is still locked. I'm actually surprised the
>>>> .getSubModel() didn't return null, but it didn't. Is this a bug
>>>> with the locking, or does the locking only apply to the objects
>>>> under the resource and not the resource itself.
>>>>
>>>> Thanks for your help!
>>>>
>>>> Sincerely,
>>>> Stephen McCants


Re: [CDO] A locked CDOView has objects removed from its model [message #424465 is a reply to message #424367] Mon, 27 October 2008 19:33 Go to previous messageGo to next message
Stephen McCants is currently offline Stephen McCantsFriend
Messages: 92
Registered: July 2009
Member
Hi Simon,
My comments are below.

>> It seems that the only way (currently) to ensure that you have a
>> consistent model is to use audits. Is that true as well?
> No. You can use on the
>
> session.setPassiveUpdateEnabled(false);
>
> you can refresh your session by calling
>
> session.refresh();
>
> You will not receive any updates!

I tried this with the tests that I posted originally and I was still failing the tests, so I moved
to using an Audit and found that it is better suited for my needs.

To help with debugging the setPassiveUpdateEnabled(false) problem, I've included the failing tests.
It sometimes fails in the first test below and sometimes in the second test.

The first failure is:

assertThat(testModel.getName(), is("Locked")); //Fails with the old value "Junit"

The second failure is:

assertThat(inResource.getContents().size(), is(2)); // Fails with the value 1

Here are the tests that use both locks and disabling the PassiveUpdate:

// Create configuration
CDOSessionConfiguration configuration = CDOUtil.createSessionConfiguration();
configuration.setLazyPackageRegistry();
configuration.setRepositoryName(CDO.getRepositoryName());
IConnector connector = TCPUtil.getConnector(IPluginContainer.INSTANCE,
InetAddress.getLocalHost().getHostName()); // TODO deactivate connector
configuration.setConnector(connector);

// Open session
CDOSession session1 = configuration.openSession();
CDOSession session2 = configuration.openSession();
session2.setPassiveUpdateEnabled(false);

CDOTransaction transaction = session1.openTransaction();
Resource outResource = transaction.createResource("/model");
Model model = JunitFactory.eINSTANCE.createModel();
model.setName("Junit");
outResource.getContents().add(model);
transaction.commit();

CDOView view = session2.openView();
Resource inResource = view.getResource("/model");
assertThat(inResource, is(notNullValue()));
assertThat(inResource.getContents().size(), is(1));
Model testModel = (Model) inResource.getContents().get(0);
assertThat(testModel.getName(), is("Junit"));

// First test
view.getLock().lock();
model.setName("Locked");
transaction.commit();
Thread.sleep(1000);
assertThat(testModel.getName(), is("Junit"));
view.getLock().unlock();
session2.refresh();
Thread.sleep(1000);
assertThat(testModel.getName(), is("Locked"));

// Second test: Add a sub model and make sure that works.
view.getLock().lock();
Model subModel = JunitFactory.eINSTANCE.createModel();
subModel.setName("another name");
outResource.getContents().add(subModel);
model.setSubModel(subModel);
transaction.commit();
Thread.sleep(1000);
assertThat(testModel.getSubModel(), nullValue());
view.getLock().unlock();
session2.refresh();
Thread.sleep(1000);
assertThat(testModel.getSubModel(), notNullValue());
assertThat(testModel.getSubModel().getName(), is("another name"));

Thanks for your help.

Sincerely,
Stephen McCants
Re: [CDO] A locked CDOView has objects removed from its model [message #424466 is a reply to message #424437] Mon, 27 October 2008 19:53 Go to previous messageGo to next message
Stephen McCants is currently offline Stephen McCantsFriend
Messages: 92
Registered: July 2009
Member
Hello Eike,

>> Hi Simon,
>> Okay, I think I understand this and it makes sense. The View can
>> only lock objects that it has (i.e. objects in the CLEAN state) and
>> cannot lock object that it hasn't loaded (i.e. objects in the PROXY
>> state).
>> That makes sense to me, but I think there can be subtle problems.
>> Let's consider a CDO model with ObjectA (rev 1) and ObjectB (rev 1) in
>> it. A View is locked and loads ObjectA (rev 1). Now a separate
>> transaction changes ObjectA and ObjectB and commits the change which
>> sets them to "rev 2". The locked View will see ObjectA (rev 1) still,
>> but if it loads ObjectB after the commit, then it will get ObjectB
>> (rev 2). In that case it would be seeing a model that is potentially
>> inconsistent and has half of a committed transaction.
> Locking a CDOView means to block the background thread that processes
> the remote change notifications from "invalidating" the objects in the
> view. As soon as you unlock the view the blocked notifications are
> processed and the objects invalidated. Such change notifications always
> contain the information about all objects that were changed in a remote
> transaction. Depending on whether you are currently holding the view
> lock or not either all changed objects are invalidated or none of them
> (until you release the lock).
>
> I would say that the usage of the view lock can not lead to inconcistent
> data being visible. Or dou you mean something else?

As I understood what Simon explained, if you have not accessed an object through a View, then it
will not be loaded into the View (i.e. lazy loading of objects into a View). That means, when you
do access it, you will get the most recent version of it from the Session/CDO back end.

Let's consider a View that has Object A cached (loaded) and has not loaded Object B. The code locks
the View so the cache will continue to hold Object A at revision 1 by making invalidation
notifications wait on the lock. If some transaction changes Object A & B to revision 2 in the same
transaction.commit() call, the View's cache will continue to hold Object A at revision 1. That is
desirable from my point of view.

However, if we now load Object B through the View we will get revision 2 from the CDO back end and
store that in the View's cache. So, the View now has Object A at revision 1 and Object B at
revision 2 and these are locked so they will not change in the View cache until they are unlocked.
This is a problem since the transaction that moved Object B to revision 2 also changed Object A to
revision 2, but the View only shows half the transaction's changes. That is it only shows the
changes to Object B and not the changes to Object A. Of course, I really wanted to see only
revision 1 and see none of the changes.

I'm not sure I've done a very good job of explaining the problem, but I hope that helps.

I switched to Audits for my code to work around this problem. Since it fetches the version based on
a particular time, I won't risk seeing only pieces of a transaction or having invalidations
interrupt what I'm currently doing with the model.

I hope that explanation helps. It is, of course, possible that I'm thinking about this the wrong
way, but it does match with what I was seeing in my code.

Sincerely,
Stephen McCants
Re: [CDO] A locked CDOView has objects removed from its model [message #424468 is a reply to message #424465] Mon, 27 October 2008 20:36 Go to previous messageGo to next message
Simon Mc Duff is currently offline Simon Mc DuffFriend
Messages: 596
Registered: July 2009
Senior Member
I tested your testcase and cannot reproduce it.
I tested it with DBStore and MySql and MEMStore.

It succeed for both of them.
To make sure event are sent properly.. can you wait let say 5000
milliseconds after the refresh.

Eike, I personnaly think that when we refresh the invalidation process
shouldn't go through another thread... what do you think ?

Simon


Stephen McCants wrote:
> Hi Simon,
> My comments are below.
>
>>> It seems that the only way (currently) to ensure that you have a
>>> consistent model is to use audits. Is that true as well?
>> No. You can use on the
>>
>> session.setPassiveUpdateEnabled(false);
>>
>> you can refresh your session by calling
>>
>> session.refresh();
>>
>> You will not receive any updates!
>
> I tried this with the tests that I posted originally and I was still
> failing the tests, so I moved to using an Audit and found that it is
> better suited for my needs.
>
> To help with debugging the setPassiveUpdateEnabled(false) problem, I've
> included the failing tests. It sometimes fails in the first test below
> and sometimes in the second test.
>
> The first failure is:
>
> assertThat(testModel.getName(), is("Locked")); //Fails with the old
> value "Junit"
>
> The second failure is:
>
> assertThat(inResource.getContents().size(), is(2)); // Fails with the
> value 1
>
> Here are the tests that use both locks and disabling the PassiveUpdate:
>
> // Create configuration
> CDOSessionConfiguration configuration =
> CDOUtil.createSessionConfiguration();
> configuration.setLazyPackageRegistry();
> configuration.setRepositoryName(CDO.getRepositoryName());
> IConnector connector =
> TCPUtil.getConnector(IPluginContainer.INSTANCE,
> InetAddress.getLocalHost().getHostName()); // TODO deactivate connector
> configuration.setConnector(connector);
>
> // Open session
> CDOSession session1 = configuration.openSession();
> CDOSession session2 = configuration.openSession();
> session2.setPassiveUpdateEnabled(false);
>
> CDOTransaction transaction = session1.openTransaction();
> Resource outResource = transaction.createResource("/model");
> Model model = JunitFactory.eINSTANCE.createModel();
> model.setName("Junit");
> outResource.getContents().add(model);
> transaction.commit();
>
> CDOView view = session2.openView();
> Resource inResource = view.getResource("/model");
> assertThat(inResource, is(notNullValue()));
> assertThat(inResource.getContents().size(), is(1));
> Model testModel = (Model) inResource.getContents().get(0);
> assertThat(testModel.getName(), is("Junit"));
>
> // First test
> view.getLock().lock();
> model.setName("Locked");
> transaction.commit();
> Thread.sleep(1000);
> assertThat(testModel.getName(), is("Junit"));
> view.getLock().unlock();
> session2.refresh();
> Thread.sleep(1000);
> assertThat(testModel.getName(), is("Locked"));
>
> // Second test: Add a sub model and make sure that works.
> view.getLock().lock();
> Model subModel = JunitFactory.eINSTANCE.createModel();
> subModel.setName("another name");
> outResource.getContents().add(subModel);
> model.setSubModel(subModel);
> transaction.commit();
> Thread.sleep(1000);
> assertThat(testModel.getSubModel(), nullValue());
> view.getLock().unlock();
> session2.refresh();
> Thread.sleep(1000);
> assertThat(testModel.getSubModel(), notNullValue());
> assertThat(testModel.getSubModel().getName(), is("another name"));
>
> Thanks for your help.
>
> Sincerely,
> Stephen McCants
Re: [CDO] A locked CDOView has objects removed from its model [message #424469 is a reply to message #424466] Mon, 27 October 2008 20:42 Go to previous messageGo to next message
Simon Mc Duff is currently offline Simon Mc DuffFriend
Messages: 596
Registered: July 2009
Senior Member
Stephen McCants wrote:
> Hello Eike,
>
>>> Hi Simon,
>>> Okay, I think I understand this and it makes sense. The View can
>>> only lock objects that it has (i.e. objects in the CLEAN state) and
>>> cannot lock object that it hasn't loaded (i.e. objects in the PROXY
>>> state).
>>> That makes sense to me, but I think there can be subtle
>>> problems. Let's consider a CDO model with ObjectA (rev 1) and
>>> ObjectB (rev 1) in it. A View is locked and loads ObjectA (rev 1).
>>> Now a separate transaction changes ObjectA and ObjectB and commits
>>> the change which sets them to "rev 2". The locked View will see
>>> ObjectA (rev 1) still, but if it loads ObjectB after the commit, then
>>> it will get ObjectB (rev 2). In that case it would be seeing a model
>>> that is potentially inconsistent and has half of a committed
>>> transaction.
>> Locking a CDOView means to block the background thread that processes
>> the remote change notifications from "invalidating" the objects in the
>> view. As soon as you unlock the view the blocked notifications are
>> processed and the objects invalidated. Such change notifications
>> always contain the information about all objects that were changed in
>> a remote transaction. Depending on whether you are currently holding
>> the view lock or not either all changed objects are invalidated or
>> none of them (until you release the lock).
>>
>> I would say that the usage of the view lock can not lead to
>> inconcistent data being visible. Or dou you mean something else?
>
> As I understood what Simon explained, if you have not accessed an object
> through a View, then it will not be loaded into the View (i.e. lazy
> loading of objects into a View). That means, when you do access it, you
> will get the most recent version of it from the Session/CDO back end.
>
> Let's consider a View that has Object A cached (loaded) and has not
> loaded Object B. The code locks the View so the cache will continue to
> hold Object A at revision 1 by making invalidation notifications wait on
> the lock. If some transaction changes Object A & B to revision 2 in the
> same transaction.commit() call, the View's cache will continue to hold
> Object A at revision 1. That is desirable from my point of view.
>
> However, if we now load Object B through the View we will get revision 2
> from the CDO back end and store that in the View's cache. So, the View
> now has Object A at revision 1 and Object B at revision 2 and these are
> locked so they will not change in the View cache until they are
> unlocked. This is a problem since the transaction that moved Object B to
> revision 2 also changed Object A to revision 2, but the View only shows
> half the transaction's changes. That is it only shows the changes to
> Object B and not the changes to Object A. Of course, I really wanted to
> see only revision 1 and see none of the changes.
>
> I'm not sure I've done a very good job of explaining the problem, but I
> hope that helps.
Yes you did.
Yes this is a problem... that many layer like us will have .. and even
relational database as well.
But by putting setPassiveUpdateEnables(false) the back-end will do at
its best to give you the right objects (By using the same transaction ..
and not refreshing their cache).
But since we are working with a partial data.. you will agree that this
could be complicated for the back-end. Not all back-end could support
that otherwise they will need to load many objects or so.

>
> I switched to Audits for my code to work around this problem. Since it
> fetches the version based on a particular time, I won't risk seeing only
> pieces of a transaction or having invalidations interrupt what I'm
> currently doing with the model.
Audit will be good for your case.
>
> I hope that explanation helps. It is, of course, possible that I'm
> thinking about this the wrong way, but it does match with what I was
> seeing in my code.
>
> Sincerely,
> Stephen McCants
>
>
Re: [CDO] A locked CDOView has objects removed from its model [message #424478 is a reply to message #424468] Tue, 28 October 2008 06:26 Go to previous messageGo to next message
Eike Stepper is currently offline Eike StepperFriend
Messages: 6682
Registered: July 2009
Senior Member
Simon McDuff schrieb:
> I tested your testcase and cannot reproduce it.
> I tested it with DBStore and MySql and MEMStore.
>
> It succeed for both of them.
> To make sure event are sent properly.. can you wait let say 5000
> milliseconds after the refresh.
>
> Eike, I personnaly think that when we refresh the invalidation process
> shouldn't go through another thread... what do you think ?
Yes, I definitely agree! We should handle the refresh response
synchronously and not acquire the view lock.
Do we have a Bugzilla for this issue?

Cheers
/Eike



>
> Simon
>
>
> Stephen McCants wrote:
>> Hi Simon,
>> My comments are below.
>>
>>>> It seems that the only way (currently) to ensure that you have
>>>> a consistent model is to use audits. Is that true as well?
>>> No. You can use on the
>>>
>>> session.setPassiveUpdateEnabled(false);
>>>
>>> you can refresh your session by calling
>>>
>>> session.refresh();
>>>
>>> You will not receive any updates!
>>
>> I tried this with the tests that I posted originally and I was still
>> failing the tests, so I moved to using an Audit and found that it is
>> better suited for my needs.
>>
>> To help with debugging the setPassiveUpdateEnabled(false) problem,
>> I've included the failing tests. It sometimes fails in the first
>> test below and sometimes in the second test.
>>
>> The first failure is:
>>
>> assertThat(testModel.getName(), is("Locked")); //Fails with the old
>> value "Junit"
>>
>> The second failure is:
>>
>> assertThat(inResource.getContents().size(), is(2)); // Fails with the
>> value 1
>>
>> Here are the tests that use both locks and disabling the PassiveUpdate:
>>
>> // Create configuration
>> CDOSessionConfiguration configuration =
>> CDOUtil.createSessionConfiguration();
>> configuration.setLazyPackageRegistry();
>> configuration.setRepositoryName(CDO.getRepositoryName());
>> IConnector connector =
>> TCPUtil.getConnector(IPluginContainer.INSTANCE,
>> InetAddress.getLocalHost().getHostName()); // TODO deactivate connector
>> configuration.setConnector(connector);
>>
>> // Open session
>> CDOSession session1 = configuration.openSession();
>> CDOSession session2 = configuration.openSession();
>> session2.setPassiveUpdateEnabled(false);
>>
>> CDOTransaction transaction = session1.openTransaction();
>> Resource outResource = transaction.createResource("/model");
>> Model model = JunitFactory.eINSTANCE.createModel();
>> model.setName("Junit");
>> outResource.getContents().add(model);
>> transaction.commit();
>>
>> CDOView view = session2.openView();
>> Resource inResource = view.getResource("/model");
>> assertThat(inResource, is(notNullValue()));
>> assertThat(inResource.getContents().size(), is(1));
>> Model testModel = (Model) inResource.getContents().get(0);
>> assertThat(testModel.getName(), is("Junit"));
>>
>> // First test
>> view.getLock().lock();
>> model.setName("Locked");
>> transaction.commit();
>> Thread.sleep(1000);
>> assertThat(testModel.getName(), is("Junit"));
>> view.getLock().unlock();
>> session2.refresh();
>> Thread.sleep(1000);
>> assertThat(testModel.getName(), is("Locked"));
>>
>> // Second test: Add a sub model and make sure that works.
>> view.getLock().lock();
>> Model subModel = JunitFactory.eINSTANCE.createModel();
>> subModel.setName("another name");
>> outResource.getContents().add(subModel);
>> model.setSubModel(subModel);
>> transaction.commit();
>> Thread.sleep(1000);
>> assertThat(testModel.getSubModel(), nullValue());
>> view.getLock().unlock();
>> session2.refresh();
>> Thread.sleep(1000);
>> assertThat(testModel.getSubModel(), notNullValue());
>> assertThat(testModel.getSubModel().getName(), is("another name"));
>>
>> Thanks for your help.
>>
>> Sincerely,
>> Stephen McCants


Re: [CDO] A locked CDOView has objects removed from its model [message #424479 is a reply to message #424466] Tue, 28 October 2008 06:41 Go to previous messageGo to next message
Eike Stepper is currently offline Eike StepperFriend
Messages: 6682
Registered: July 2009
Senior Member
Hi Stephen,

I agree with Simon in that:

1) You've explained the problem very well ;-)
2) The issue you've explained is more related with lazy loading (from a
floating baseline) in general than with locking the view against remote
invalidation.
3) A good solution is using an additional audit view with a fixed
baseline. Such an audit view on the same session should not incur too
much overhead since most of the revisions should already be in the local
session cache.

Do you think that we could do something completely new to support your
use cases?
Maybe this Bugzilla is also related:

247427: Explicit locking
https://bugs.eclipse.org/bugs/show_bug.cgi?id=247427

Cheers
/Eike


Stephen McCants schrieb:
> Hello Eike,
>
>>> Hi Simon,
>>> Okay, I think I understand this and it makes sense. The View
>>> can only lock objects that it has (i.e. objects in the CLEAN state)
>>> and cannot lock object that it hasn't loaded (i.e. objects in the
>>> PROXY state).
>>> That makes sense to me, but I think there can be subtle
>>> problems. Let's consider a CDO model with ObjectA (rev 1) and
>>> ObjectB (rev 1) in it. A View is locked and loads ObjectA (rev 1).
>>> Now a separate transaction changes ObjectA and ObjectB and commits
>>> the change which sets them to "rev 2". The locked View will see
>>> ObjectA (rev 1) still, but if it loads ObjectB after the commit,
>>> then it will get ObjectB (rev 2). In that case it would be seeing a
>>> model that is potentially inconsistent and has half of a committed
>>> transaction.
>> Locking a CDOView means to block the background thread that processes
>> the remote change notifications from "invalidating" the objects in
>> the view. As soon as you unlock the view the blocked notifications
>> are processed and the objects invalidated. Such change notifications
>> always contain the information about all objects that were changed in
>> a remote transaction. Depending on whether you are currently holding
>> the view lock or not either all changed objects are invalidated or
>> none of them (until you release the lock).
>>
>> I would say that the usage of the view lock can not lead to
>> inconcistent data being visible. Or dou you mean something else?
>
> As I understood what Simon explained, if you have not accessed an
> object through a View, then it will not be loaded into the View (i.e.
> lazy loading of objects into a View). That means, when you do access
> it, you will get the most recent version of it from the Session/CDO
> back end.
>
> Let's consider a View that has Object A cached (loaded) and has not
> loaded Object B. The code locks the View so the cache will continue
> to hold Object A at revision 1 by making invalidation notifications
> wait on the lock. If some transaction changes Object A & B to
> revision 2 in the same transaction.commit() call, the View's cache
> will continue to hold Object A at revision 1. That is desirable from
> my point of view.
>
> However, if we now load Object B through the View we will get revision
> 2 from the CDO back end and store that in the View's cache. So, the
> View now has Object A at revision 1 and Object B at revision 2 and
> these are locked so they will not change in the View cache until they
> are unlocked. This is a problem since the transaction that moved
> Object B to revision 2 also changed Object A to revision 2, but the
> View only shows half the transaction's changes. That is it only shows
> the changes to Object B and not the changes to Object A. Of course, I
> really wanted to see only revision 1 and see none of the changes.
>
> I'm not sure I've done a very good job of explaining the problem, but
> I hope that helps.
>
> I switched to Audits for my code to work around this problem. Since
> it fetches the version based on a particular time, I won't risk seeing
> only pieces of a transaction or having invalidations interrupt what
> I'm currently doing with the model.
>
> I hope that explanation helps. It is, of course, possible that I'm
> thinking about this the wrong way, but it does match with what I was
> seeing in my code.
>
> Sincerely,
> Stephen McCants
>
>


Re: [CDO] A locked CDOView has objects removed from its model [message #424502 is a reply to message #424478] Tue, 28 October 2008 16:35 Go to previous message
Simon Mc Duff is currently offline Simon Mc DuffFriend
Messages: 596
Registered: July 2009
Senior Member
Eike Stepper wrote:
> Simon McDuff schrieb:
>> I tested your testcase and cannot reproduce it.
>> I tested it with DBStore and MySql and MEMStore.
>>
>> It succeed for both of them.
>> To make sure event are sent properly.. can you wait let say 5000
>> milliseconds after the refresh.
>>
>> Eike, I personnaly think that when we refresh the invalidation process
>> shouldn't go through another thread... what do you think ?
> Yes, I definitely agree! We should handle the refresh response
> synchronously and not acquire the view lock.
> Do we have a Bugzilla for this issue?
252362: session.refresh should not go through lock/thread invalidation
https://bugs.eclipse.org/bugs/show_bug.cgi?id=252362
>
> Cheers
> /Eike
>
>
>
>>
>> Simon
>>
>>
>> Stephen McCants wrote:
>>> Hi Simon,
>>> My comments are below.
>>>
>>>>> It seems that the only way (currently) to ensure that you have
>>>>> a consistent model is to use audits. Is that true as well?
>>>> No. You can use on the
>>>>
>>>> session.setPassiveUpdateEnabled(false);
>>>>
>>>> you can refresh your session by calling
>>>>
>>>> session.refresh();
>>>>
>>>> You will not receive any updates!
>>>
>>> I tried this with the tests that I posted originally and I was still
>>> failing the tests, so I moved to using an Audit and found that it is
>>> better suited for my needs.
>>>
>>> To help with debugging the setPassiveUpdateEnabled(false) problem,
>>> I've included the failing tests. It sometimes fails in the first
>>> test below and sometimes in the second test.
>>>
>>> The first failure is:
>>>
>>> assertThat(testModel.getName(), is("Locked")); //Fails with the old
>>> value "Junit"
>>>
>>> The second failure is:
>>>
>>> assertThat(inResource.getContents().size(), is(2)); // Fails with the
>>> value 1
>>>
>>> Here are the tests that use both locks and disabling the PassiveUpdate:
>>>
>>> // Create configuration
>>> CDOSessionConfiguration configuration =
>>> CDOUtil.createSessionConfiguration();
>>> configuration.setLazyPackageRegistry();
>>> configuration.setRepositoryName(CDO.getRepositoryName());
>>> IConnector connector =
>>> TCPUtil.getConnector(IPluginContainer.INSTANCE,
>>> InetAddress.getLocalHost().getHostName()); // TODO deactivate connector
>>> configuration.setConnector(connector);
>>>
>>> // Open session
>>> CDOSession session1 = configuration.openSession();
>>> CDOSession session2 = configuration.openSession();
>>> session2.setPassiveUpdateEnabled(false);
>>>
>>> CDOTransaction transaction = session1.openTransaction();
>>> Resource outResource = transaction.createResource("/model");
>>> Model model = JunitFactory.eINSTANCE.createModel();
>>> model.setName("Junit");
>>> outResource.getContents().add(model);
>>> transaction.commit();
>>>
>>> CDOView view = session2.openView();
>>> Resource inResource = view.getResource("/model");
>>> assertThat(inResource, is(notNullValue()));
>>> assertThat(inResource.getContents().size(), is(1));
>>> Model testModel = (Model) inResource.getContents().get(0);
>>> assertThat(testModel.getName(), is("Junit"));
>>>
>>> // First test
>>> view.getLock().lock();
>>> model.setName("Locked");
>>> transaction.commit();
>>> Thread.sleep(1000);
>>> assertThat(testModel.getName(), is("Junit"));
>>> view.getLock().unlock();
>>> session2.refresh();
>>> Thread.sleep(1000);
>>> assertThat(testModel.getName(), is("Locked"));
>>>
>>> // Second test: Add a sub model and make sure that works.
>>> view.getLock().lock();
>>> Model subModel = JunitFactory.eINSTANCE.createModel();
>>> subModel.setName("another name");
>>> outResource.getContents().add(subModel);
>>> model.setSubModel(subModel);
>>> transaction.commit();
>>> Thread.sleep(1000);
>>> assertThat(testModel.getSubModel(), nullValue());
>>> view.getLock().unlock();
>>> session2.refresh();
>>> Thread.sleep(1000);
>>> assertThat(testModel.getSubModel(), notNullValue());
>>> assertThat(testModel.getSubModel().getName(), is("another name"));
>>>
>>> Thanks for your help.
>>>
>>> Sincerely,
>>> Stephen McCants
Previous Topic:Dangling EObjects (are in NO resource) during serialization
Next Topic:[Teneo] Generated Many to Many not populating resolving table
Goto Forum:
  


Current Time: Fri Apr 26 06:36:34 GMT 2024

Powered by FUDForum. Page generated in 0.04623 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top