Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » [ChangeRecoder] Problem with beginRecording() after endRecording() was called
[ChangeRecoder] Problem with beginRecording() after endRecording() was called [message #1260575] Sat, 01 March 2014 16:58 Go to next message
Silvestre Martins is currently offline Silvestre Martins
Messages: 41
Registered: July 2009
Member
I have the following scenario where the change recorder is used:

When ChangeRecorder is used the first time, I create a new instance and register it as an adapter of the root object I want to keep track of changes. This registers the ChangeRecorder recursively in every object of the tree.

After the concrete use-case is finished, the endRecording() is called and the ChangeDescription.apply() is performed to rollback the changes.
Since I might need it later, I don't dispose() it, so I can save computation.


Does the ChangeRecorder supports this scenario where changes on the model may occur while the ChangeRecorder was already attached but is not recording (including the rollback of changes) and new objects might have been added to the model?

I'm asking because my code fails when I use the ChangeRecorder is this way, but it succeeds if I simply dispose the ChangeRecorder after using it and create a fresh instance every time I want to start a restore point.
However disposing it seems too overkill because in a big model it will spend a lot of time disposing and attaching the ChangeRecorder to the whole tree every time I need it, so I was trying to find a way to reuse it.

[Updated on: Sat, 01 March 2014 16:59]

Report message to a moderator

Re: [ChangeRecoder] Problem with beginRecording() after endRecording() was called [message #1260583 is a reply to message #1260575] Sat, 01 March 2014 17:09 Go to previous messageGo to next message
Ed Merks is currently offline Ed Merks
Messages: 26044
Registered: July 2009
Senior Member
Silvestre,

Comments below.

On 01/03/2014 5:58 PM, Silvestre Martins wrote:
>
> I have the following scenario where the change recorder is used:
>
> When ChangeRecorder is used the first time, I create a new instance
> and register it as an adapter of the root object I want to keep track
> of changes. This registers the ChangeRecorder recursively in every
> object of the tree.
>
> After the concrete use-case is finished, the endRecording() is called
> and the ChangeDescription.apply() is performed to rollback the
> changes. Since I might need it later, I don't dispose() it, so I can
> save computation.
The change description is not in good shape unless you call
applyAndReverse, in which case it's a reverse description you can apply
against to "unrollback" the changes...
>
> Does the ChangeRecorder supports this scenario where changes on the
> model may occur while the ChangeRecorder was already attached but is
> not recording (including the rollback of changes) and new objects
> might have been added to the model?
No, endRecording is the end.
>
> I'm asking because my code fails when I use the ChangeRecorder is this
> way, but it succeeds if I simply dispose the ChangeRecorder after
> using it and create a fresh instance every time I want to start a
> restore point.
Yes, that's the way.
> However disposing it seems to overkill because in a big model it will
> spend a lot of time disposing and attaching the ChangeRecorder to the
> whole tree every time I need it, so I was trying to find a way to
> reuse it.
Try summarize().
>
>
Re: [ChangeRecoder] Problem with beginRecording() after endRecording() was called [message #1367085 is a reply to message #1260575] Mon, 19 May 2014 16:21 Go to previous messageGo to next message
Silvestre Martins is currently offline Silvestre Martins
Messages: 41
Registered: July 2009
Member
In the meantime I was evaluating another usage for this - to add some context:
the purpose of this ChangeRecorder is to have a restore point in case a command fails, and disposing and attaching a new ChangeRecorder instance of each command is very expensive, so my goal is to reuse the ChangeRecorder.
Calling summarize() doesn't help because the goal is to start recording always when a command is about to start, so in case of failure it rollbacks only the changes of that command.

So my idea was to instantiate a ChangeRecorder at the first time and call beginRecording(). After the command finishes with success I simply call changeRecorder.setChangeDescription(null) to release recorded data, but do not end recording neither dispose the ChangeRecorder.

Then for each new command, I do always the the same: before it starts executing I call beginRecording(), and again set the ChangeDescription to null at the end, if commands ends successfully.

Only if there is an exception I will call ChangeRecorder.endRecording() and call apply() on it. In this case I will dispose the ChangeRecorder and a attach a new one, but since these are the exception scenarios, it's ok for me.

Is this usage supported?
In simple words: can the beginRecording() be called several times for the same ChangeRecorder instance?

[Updated on: Mon, 19 May 2014 16:40]

Report message to a moderator

Re: [ChangeRecoder] Problem with beginRecording() after endRecording() was called [message #1367136 is a reply to message #1367085] Mon, 19 May 2014 16:52 Go to previous messageGo to next message
Ed Merks is currently offline Ed Merks
Messages: 26044
Registered: July 2009
Senior Member
Silvestre,

Comments below.

On 19/05/2014 6:21 PM, Silvestre Martins wrote:
> In the meantime I was evaluating another usage for this - to add some
> context: the purpose of this ChangeRecorder is to have a restore point
> in case a command fails, and disposing and attaching a new
> ChangeRecorder instance of each command is very expensive.
It depends on which objects you attach it to. Of course attaching to
the whole resource set is most expensive. Attaching it only to the
objects you're planning to change is likely quite cheap.
> Calling summarize() doesn't help because the goal is to start
> recording always when a command is about to start, so in case of
> failure it rollbacks only the changes of that command.
>
> So my idea was to instantiate a ChangeRecorder at the first time and
> call beginRecording().
This call remembers things like the attachment state of objects at the
point in time...
> After the command finishes with success I simply call
> changeRecorder.setChangeDescription(null) to release recorded data,
> but do not end recording neither dispose the ChangeRecorder.
The overlooks the attachment state that's import for knowing which
objects needed to be added or remove from the containment treee.
>
> Then for each new command, I do the always the same: before it starts
> executing I call beginRecording(), and again set the ChangeDescription
> to null at the end, if commands ends successfully.
>
> Only if there is an exception I will call
> ChangeRecorder.endRecording() and call apply() on it. In this case I
> will dispose the ChangeRecorder and a attach a new one, but since
> these are the exception scenarios, it's ok for me.
How much do you know ahead of time in terms of which objects are
potentially affected by your commands?
>
> Is this usage supported?
> In simple words: can the beginRecording() be called several times for
> the same ChangeRecorder instance even when we are not resuming the
> recording?
Not really. Visiting the whole containment tree is important...
>
>
Re: [ChangeRecoder] Problem with beginRecording() after endRecording() was called [message #1370129 is a reply to message #1367136] Tue, 20 May 2014 22:13 Go to previous messageGo to next message
Silvestre Martins is currently offline Silvestre Martins
Messages: 41
Registered: July 2009
Member
In this model is not feasible to only attach to a part of the model because the changes may (potentially) spread along the entire model, so we are not able to determine with 100% certainty which objects to track, without refactoring the commands and the underlying business logic.

But after looking better to the ChangeRecorder implementation, it seems to me that we can reuse it by simply updating the originalTargetObjects list to include all content of targetObjects list when beginRecording() is called. I think this will leave the ChangeRecorder in the same state as if beginRecording() was not never called before, right?

public void beginRecording(...) {
    originalTargetObjects.clear();
    originalTargetObjects.addAll(targetObjects);
    
    ...
}


I did some experiences with this approach and it seems is working fine.

Does this makes sense or did I miss something?
Re: [ChangeRecoder] Problem with beginRecording() after endRecording() was called [message #1370792 is a reply to message #1370129] Wed, 21 May 2014 05:04 Go to previous messageGo to next message
Ed Merks is currently offline Ed Merks
Messages: 26044
Registered: July 2009
Senior Member
Silvestre,

One thing this approach overlooks (likely the only thing) is that the
targetObjects can contain things no longer attached to the tree, i.e.,
the objects that have been deleted, but you could test for that as well
by filtering the addAll.


On 21/05/2014 12:13 AM, Silvestre Martins wrote:
> In this model is not feasible to only attach to a part of the model
> because the changes may (potentially) spread along the entire model,
> so we are not able to determine with 100% certainty which objects to
> track, without refactoring the commands and the underlying business
> logic.
>
> But after looking better to the ChangeRecorder implementation, it
> seems to me that we can reuse it by simply updating the
> originalTargetObjects list to include all content of targetObjects
> list when beginRecording() is called. I think this will leave the
> ChangeRecorder in the same state as if beginRecording() was not never
> called before, right?
>
>
> public void beginRecording(...) {
> originalTargetObjects.clear();
> originalTargetObjects.addAll(targetObjects);
> ...
> }
>
>
> I did some experiences with this approach and it seems is working fine.
>
> Does this makes sense or did I miss something?
>
Re: [ChangeRecoder] Problem with beginRecording() after endRecording() was called [message #1371280 is a reply to message #1370792] Wed, 21 May 2014 09:47 Go to previous messageGo to next message
Silvestre Martins is currently offline Silvestre Martins
Messages: 41
Registered: July 2009
Member
Well, besides a potential root for memory leaks, it would only cause problems if, for some reason, the objects gets attached again, which is very unlikely.

But we can perform a filtering, as you mentioned. The problem is that this may also be a complex operation when the addAll() is adding thousands of elements.
I will check this.

Thanks.


Ed Merks wrote on Wed, 21 May 2014 01:04
Silvestre,

One thing this approach overlooks (likely the only thing) is that the
targetObjects can contain things no longer attached to the tree, i.e.,
the objects that have been deleted, but you could test for that as well
by filtering the addAll.


On 21/05/2014 12:13 AM, Silvestre Martins wrote:
> In this model is not feasible to only attach to a part of the model
> because the changes may (potentially) spread along the entire model,
> so we are not able to determine with 100% certainty which objects to
> track, without refactoring the commands and the underlying business
> logic.
>
> But after looking better to the ChangeRecorder implementation, it
> seems to me that we can reuse it by simply updating the
> originalTargetObjects list to include all content of targetObjects
> list when beginRecording() is called. I think this will leave the
> ChangeRecorder in the same state as if beginRecording() was not never
> called before, right?
>
>
> public void beginRecording(...) {
> originalTargetObjects.clear();
> originalTargetObjects.addAll(targetObjects);
> ...
> }
>
>
> I did some experiences with this approach and it seems is working fine.
>
> Does this makes sense or did I miss something?
>

Re: [ChangeRecoder] Problem with beginRecording() after endRecording() was called [message #1371710 is a reply to message #1371280] Wed, 21 May 2014 14:05 Go to previous messageGo to next message
Silvestre Martins is currently offline Silvestre Martins
Messages: 41
Registered: July 2009
Member
A way to filter out the non-contained objects from the targetObjects list could be by maintaining a list of detached objects between calls to beginRecording(). Then in each call to beginRecording() we could simply remove all objects that were detached since last call:

public void beginRecording(...) {
    targetObjects.removeAll(detachedObjects);
    originalTargetObjects.clear();
    originalTargetObjects.addAll(targetObjects);
    
    ...
}


Then we would also need to update the detachedObjects list when an object is detached or attached from its container. This could be easily done by intercepting handleFeature(...).

I think this approach may be more efficient than iterating over the complete list of targetObjects in every call, since it is expected that the list of detached objects or the amount of detach/attach occurrences is significantly lower than the full list of objects in the resource, especially for big models.

[Updated on: Wed, 21 May 2014 14:24]

Report message to a moderator

Re: [ChangeRecoder] Problem with beginRecording() after endRecording() was called [message #1372116 is a reply to message #1371710] Wed, 21 May 2014 17:41 Go to previous message
Ed Merks is currently offline Ed Merks
Messages: 26044
Registered: July 2009
Senior Member
Silvestre,

It sounds like generally the right direction, though I know from long
experience that nasty corner cases seems always to be lurking....

On 21/05/2014 4:05 PM, Silvestre Martins wrote:
> A way to filter out the non-contained objects the targetObjects list
> could be by maintaining a list of detached objects between calls to
> beginRecording(). Then in each call to beginRecording() we could
> simply remove all objects that were detached since last call:
>
>
> public void beginRecording(...) {
> targetObjects.removeAll(detachedObjects);
> originalTargetObjects.clear();
> originalTargetObjects.addAll(targetObjects);
> ...
> }
>
>
> Then we would also need to update the detachedObjects list when an
> object detached or attached from its container. This could be easily
> done by intercepting handleFeature(...).
>
> I think this approach may be more efficient than iterating over the
> complete list of targetObjects in every call, since it is expected
> that the list of detached objects or the amount of detach/attach
> occurrences is significantly lower than the full list of objects in
> the resource, especially for big models.
Previous Topic:[EMF] Validation framework: constrain instances (instead of classes)
Next Topic:xsdecorebuilder : how to recognise an xsd:element simpletype from an xsd:attribute
Goto Forum:
  


Current Time: Tue Sep 16 07:46:01 GMT 2014

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

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