Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » Editor Unloading, Concurrency and Persistence
Editor Unloading, Concurrency and Persistence [message #535000] Fri, 21 May 2010 00:49 Go to next message
Miles Parker is currently offline Miles ParkerFriend
Messages: 1341
Registered: July 2009
Senior Member
Hi all,

I'm running into an issue with updating and saving documents and I wonder if anyone else has come up with a good solution. The scenario is basically:

1. Updating an EMF file through a long job of arbitrary durations where I don't directly control the rate of updates.
2. Periodically saving the updated contents at t % k.
3. EMF generated editor open. (I don't need/want notifications for all changes, user can refresh manually or we do it at end of session.

My basic strategy has been to queue the updates in 1 and to stop taking from the queue while performing that save for the XMLResource. The problem (I think!) I'm running into is that the save triggers a notification, which in turn synchronizes against the resource set. I've gone so far as creating a mock editor IResourceChangeListener to recreate the issue form the editor.

But forgetting all of the details, does anyone have any good guidelines / references on handling these kinds of concurrency issues while an editor is open? I didn't find anything in the book..

thanks,

Miles
Re: Editor Unloading, Concurrency and Persistence [message #535163 is a reply to message #535000] Fri, 21 May 2010 13:07 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33218
Registered: July 2009
Senior Member
Miles,

Comments below.


Miles Parker wrote:
> Hi all,
>
> I'm running into an issue with updating and saving documents and I
> wonder if anyone else has come up with a good solution. The scenario
> is basically:
>
> 1. Updating an EMF file through a long job of arbitrary durations
> where I don't directly control the rate of updates.
> 2. Periodically saving the updated contents at t % k.
> 3. EMF generated editor open. (I don't need/want notifications for all
> changes, user can refresh manually or we do it at end of session.
>
> My basic strategy has been to queue the updates in 1 and to stop
> taking from the queue while performing that save for the XMLResource.
> The problem (I think!) I'm running into is that the save triggers a
> notification, which in turn synchronizes against the resource set.
> I've gone so far as creating a mock editor IResourceChangeListener to
> recreate the issue form the editor.
There's a workspace delta listener in the generated editor and it will
definitely sync up the editor with what's in the workspace when the
workspace is updated.
>
> But forgetting all of the details, does anyone have any good
> guidelines / references on handling these kinds of concurrency issues
> while an editor is open? I didn't find anything in the book..
If the workspace copy is different from the editor's copy there's a
danger that the user will modify an out of date copy and save that over
top of changes being made in the background job. How should that be
resolved? Should the user be prevented from editing at all while the
job is running? I'm not sure...
>
> thanks,
>
> Miles


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: Editor Unloading, Concurrency and Persistence [message #535240 is a reply to message #535163] Fri, 21 May 2010 17:15 Go to previous messageGo to next message
Miles Parker is currently offline Miles ParkerFriend
Messages: 1341
Registered: July 2009
Senior Member

Hi Ed,

thanks as always, reply below..

Ed Merks wrote on Fri, 21 May 2010 09:07
Miles,
> The problem (I think!) I'm running into is that the save triggers a
> notification, which in turn synchronizes against the resource set.
> I've gone so far as creating a mock editor IResourceChangeListener to
> recreate the issue form the editor.
There's a workspace delta listener in the generated editor and it will
definitely sync up the editor with what's in the workspace when the
workspace is updated.



Yep, that's the one -- the ResourceChangeListener. It ends up calling handleActive, which I *think* actually calls the update in a UI async thread. Which means that if the user clicks on say a refresh while a change has been made from updating feed, in some (still a bit mysterious to me, but I'm getting there) cases the entire UI will lock.

Quote:

> But forgetting all of the details, does anyone have any good
> guidelines / references on handling these kinds of concurrency issues
> while an editor is open? I didn't find anything in the book..
If the workspace copy is different from the editor's copy there's a
danger that the user will modify an out of date copy and save that over
top of changes being made in the background job. How should that be
resolved? Should the user be prevented from editing at all while the
job is running? I'm not sure...



Right, I've actually seen this case where a user dialog comes up when the collection job is running and the editor thinks it needs to handle a dirty / conflicting case, but it doesn't. And so yes, what I'd like to do is just prevent the user form editing -- or more precisely, the editor from thinking that the user could be doing any editing.

I don't need concurrent editing, but it would be nice to have concurrent visualization. Worst case I could even block any visual updates from occurring during a collection. (In this case I'd probably just gray out the text or something and prevent nodes form being opened or closed, but I'd rather avoid that.) For performance reasons, I've already disabled a lot of notifications in the genmodel, such that the user or modification jobs have to manually refresh the tree after an update occurs. But when those notifications aren't disabled the active notifications work very well -- you can actually see the tree growing dynamically..

Anyway, I the root question is, is there a good pattern for "suspend all notifications" or "suspend active resource handling"? I need to do the periodic saving so that if something happens in the middle of a long run I don't lose the data that has already been collected. I could simply modify the methods that handle active resource delta changes but that means that I have to introduce an editor dependency for the collection code, which I'd much rather not have, or that I have to come up with some more complex mechanism to abstract this. My thinking is that there must be some mechanism to handle this already buried in EMF somewhere...

cheers,

Miles
Re: Editor Unloading, Concurrency and Persistence [message #535254 is a reply to message #535240] Fri, 21 May 2010 17:55 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33218
Registered: July 2009
Senior Member
Miles,

Comments below.

Miles Parker wrote:
>
> Hi Ed,
>
> thanks as always, reply below..
>
> Ed Merks wrote on Fri, 21 May 2010 09:07
>> Miles,
>> > The problem (I think!) I'm running into is that the save triggers a
>> > notification, which in turn synchronizes against the resource set.
>> > I've gone so far as creating a mock editor IResourceChangeListener
>> to > recreate the issue form the editor.
>> There's a workspace delta listener in the generated editor and it
>> will definitely sync up the editor with what's in the workspace when
>> the workspace is updated.
>
>
> Yep, that's the one -- the ResourceChangeListener. It ends up calling
> handleActive, which I *think* actually calls the update in a UI async
> thread.
Yes, because the resource deltas can come in on any thread.
> Which means that if the user clicks on say a refresh while a change
> has been made from updating feed, in some (still a bit mysterious to
> me, but I'm getting there) cases the entire UI will lock.
You mean deadlock? There's a way to get a dump of all the threads to
see what's blocked...
>
> Quote:
>> > But forgetting all of the details, does anyone have any good >
>> guidelines / references on handling these kinds of concurrency issues
>> > while an editor is open? I didn't find anything in the book..
>> If the workspace copy is different from the editor's copy there's a
>> danger that the user will modify an out of date copy and save that
>> over top of changes being made in the background job. How should
>> that be resolved? Should the user be prevented from editing at all
>> while the job is running? I'm not sure...
>
>
> Right, I've actually seen this case where a user dialog comes up when
> the collection job is running and the editor thinks it needs to handle
> a dirty / conflicting case, but it doesn't.
The editor being dirty should depend purely on the state of the command
stack...
> And so yes, what I'd like to do is just prevent the user form editing
> -- or more precisely, the editor from thinking that the user could be
> doing any editing.
You can make the resources look read-only to prevent all editing. Is
that what you want?
>
> I don't need concurrent editing, but it would be nice to have
> concurrent visualization.
A refresh when the workspace changes sounds like the right thing...
> Worst case I could even block any visual updates from occurring during
> a collection. (In this case I'd probably just gray out the text or
> something and prevent nodes form being opened or closed, but I'd
> rather avoid that.) For performance reasons, I've already disabled a
> lot of notifications in the genmodel, such that the user or
> modification jobs have to manually refresh the tree after an update
> occurs. But when those notifications aren't disabled the active
> notifications work very well -- you can actually see the tree growing
> dynamically..
Hmmm. I'm a bit confused now if the background thing is working
directly with the instance being viewed in the editor; it sounds that
way. But then I don't understand how the resource delta thing enters
the picture. Any changes should be done by saving the editor itself so
the editor is aware that it's been saved; it knows to ignore deltas that
it causes by doing a save...
>
> Anyway, I the root question is, is there a good pattern for "suspend
> all notifications" or "suspend active resource handling"?
No to either, especially the latter.
> I need to do the periodic saving so that if something happens in the
> middle of a long run I don't lose the data that has already been
> collected.
The editor needs to do that. And of course changes need to be done by
commands. Both those sound like issues.
> I could simply modify the methods that handle active resource delta
> changes but that means that I have to introduce an editor dependency
> for the collection code, which I'd much rather not have, or that I
> have to come up with some more complex mechanism to abstract this. My
> thinking is that there must be some mechanism to handle this already
> buried in EMF somewhere...
How are you expecting the editor's dirty state and command stack to be
tracking the changes and saves you're doing in the background? It seems
the collection process should be kicked off as part of a command and
saves are done by the editor after a command finishes...
>
> cheers,
>
> Miles


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: Editor Unloading, Concurrency and Persistence [message #535274 is a reply to message #535254] Fri, 21 May 2010 19:14 Go to previous messageGo to next message
Miles Parker is currently offline Miles ParkerFriend
Messages: 1341
Registered: July 2009
Senior Member
Ed, comments below..

Ed Merks wrote on Fri, 21 May 2010 13:55
Miles,
> Which means that if the user clicks on say a refresh while a change
> has been made from updating feed, in some (still a bit mysterious to
> me, but I'm getting there) cases the entire UI will lock.
You mean deadlock? There's a way to get a dump of all the threads to
see what's blocked...



Well, that's my working hypothesis. Unfortunately, it's one of those great bugs where for some reason it fails in a regular launch much more often then it does in the debugger.. :#. I could use a profiler like YourKit instead which is prob. what I'll do unless you can easily remember the other way to do this..but actually I think I have some ideas about why this might be happening. As usual, being forced to write this down has also made me have to think this through in a more disciplined way.

Quote:
> Right, I've actually seen this case where a user dialog comes up when
> the collection job is running and the editor thinks it needs to handle
> a dirty / conflicting case, but it doesn't.
The editor being dirty should depend purely on the state of the command
stack...


Right, that's what I thought. And yet I'm not using the command stack...ahem..see below..

Quote:

> I don't need concurrent editing, but it would be nice to have
> concurrent visualization.
A refresh when the workspace changes sounds like the right thing...



I have been just doing an unload and reload to force the update. But would this have an effect on other Resource within a different Resource set.

Quote:

> occurs. But when those notifications aren't disabled the active
> notifications work very well -- you can actually see the tree growing
> dynamically..
Hmmm. I'm a bit confused now if the background thing is working
directly with the instance being viewed in the editor; it sounds that
way. But then I don't understand how the resource delta thing enters
the picture. Any changes should be done by saving the editor itself so
the editor is aware that it's been saved; it knows to ignore deltas that
it causes by doing a save...



No, and here's the rub. The concurrent job is using it's own editing domain and resource set. At this point you're probably groaning, but wait, there's more below..

Quote:

> Anyway, I the root question is, is there a good pattern for "suspend
> all notifications" or "suspend active resource handling"?
No to either, especially the latter.
> I need to do the periodic saving so that if something happens in the
> middle of a long run I don't lose the data that has already been
> collected.
The editor needs to do that. And of course changes need to be done by
commands. Both those sound like issues.

--snip--

> I could simply modify the methods that handle active resource delta
> changes but that means that I have to introduce an editor dependency
> for the collection code, which I'd much rather not have, or that I
> have to come up with some more complex mechanism to abstract this. My
> thinking is that there must be some mechanism to handle this already
> buried in EMF somewhere...
How are you expecting the editor's dirty state and command stack to be
tracking the changes and saves you're doing in the background? It seems
the collection process should be kicked off as part of a command and
saves are done by the editor after a command finishes...


OK, so here's the real groaner. There are a couple of issues here.. I need to be able to have the job run:

1. On a resource regardless of whether that resource is currently being viewed in an editor or not.
2. For performance reasons, without a command stack. (This stream is coming in very quickly.)
3. (Ideally, I would use a job specific command stack where needed simply because I'd like to be able to reuse the ItemProvider logic and not have to re-implement the more complex stuff with raw ecore operations. But let's ignore that case for now!)

My thinking was that I should simply be able to make the changes and then force the editor to reload the changes when it sees that an external change has been made. That's what the resource listener mechanism is for I thought. Or perhaps it's just for the use of the editor loading the resource(s). The I guess surprising thing is that all of this worked until I started wanting to save the edited resource from an external job to the editor as well.

Another way to put this all is that this case would work perfectly, if when the job was triggered, the editor stopped treating itself as an editor and became a viewer, i.e. a passive listener to notifications. Or in the least ideal case, the job would trigger the editor to close and then reopen it when the editing is done. Then, at the point where the job is finished, the token is passed back to the editor and the editor then becomes responsible for ensuring that the model has consistent state. Again, I could do this by hacking into the editor but I would like to avoid that. I guess I could use the Transaction API or CDO or something but that's the kind of overhead I don't need and that I'd like to avoid as well. But it is sounding like the editor hack is the best / only way to accomplish this.

I just realized that one neat thing I could do is actually build up the command stack in my external thread and then pass the whole stack in and feed it over to the editor command stack. I guess this is essentially what Transactions does anyway. That would still require some mechanism to discover the active editor or create a domain manually if an editor didn't exist, but it would have some great advantages as it would allow me to break things up, handle multiple streams, drop bad streams, etc.. but again, I worry about the overhead. I guess I could always implement a bunch of commands that don't use any of the EMF reflection / feature stuff and simply execute a whole set of API changes I pass in. And I could do that with arbitrary granularity so that I could queue up a bunch of changes in one whopper of a command. Have you seen anything like that implemented?

thanks,

Miles
Re: Editor Unloading, Concurrency and Persistence [message #535278 is a reply to message #535274] Fri, 21 May 2010 19:37 Go to previous messageGo to next message
Miles Parker is currently offline Miles ParkerFriend
Messages: 1341
Registered: July 2009
Senior Member
Hmm...the more I think about it the more I think that Transactions is exactly what I do need. Not that I'm looking to add one other technology to my list.. Smile
Re: Editor Unloading, Concurrency and Persistence [message #535333 is a reply to message #535274] Sat, 22 May 2010 12:52 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33218
Registered: July 2009
Senior Member
Miles,

Comments below.

Miles Parker wrote:
> Ed, comments below..
>
> Ed Merks wrote on Fri, 21 May 2010 13:55
>> Miles,
>> > Which means that if the user clicks on say a refresh while a change
>> > has been made from updating feed, in some (still a bit mysterious
>> to > me, but I'm getting there) cases the entire UI will lock.
>> You mean deadlock? There's a way to get a dump of all the threads to
>> see what's blocked...
>
>
> Well, that's my working hypothesis. Unfortunately, it's one of those
> great bugs where for some reason it fails in a regular launch much
> more often then it does in the debugger.. :#.
You don't need to run it under the debugger.
http://wiki.eclipse.org/index.php/How_to_report_a_deadlock
> I could use a profiler like YourKit instead which is prob. what I'll
> do unless you can easily remember the other way to do this..but
> actually I think I have some ideas about why this might be happening.
> As usual, being forced to write this down has also made me have to
> think this through in a more disciplined way.
>
> Quote:
>> > Right, I've actually seen this case where a user dialog comes up
>> when > the collection job is running and the editor thinks it needs
>> to handle > a dirty / conflicting case, but it doesn't.
>> The editor being dirty should depend purely on the state of the
>> command stack...
>
>
> Right, that's what I thought. And yet I'm not using the command
> stack...ahem..see below..
> Quote:
>> > I don't need concurrent editing, but it would be nice to have >
>> concurrent visualization. A refresh when the workspace changes sounds
>> like the right thing...
>
>
> I have been just doing an unload and reload to force the update. But
> would this have an effect on other Resource within a different
> Resource set.
>
> Quote:
>> > occurs. But when those notifications aren't disabled the active >
>> notifications work very well -- you can actually see the tree growing
>> > dynamically..
>> Hmmm. I'm a bit confused now if the background thing is working
>> directly with the instance being viewed in the editor; it sounds that
>> way. But then I don't understand how the resource delta thing enters
>> the picture. Any changes should be done by saving the editor itself
>> so the editor is aware that it's been saved; it knows to ignore
>> deltas that it causes by doing a save...
>
>
> No, and here's the rub. The concurrent job is using it's own editing
> domain and resource set. At this point you're probably groaning, but
> wait, there's more below..
>
> Quote:
>> > Anyway, I the root question is, is there a good pattern for
>> "suspend > all notifications" or "suspend active resource handling"?
>> No to either, especially the latter.
>> > I need to do the periodic saving so that if something happens in
>> the > middle of a long run I don't lose the data that has already
>> been > collected. The editor needs to do that. And of course changes
>> need to be done by commands. Both those sound like issues.
>>
>> --snip--
>>
>> > I could simply modify the methods that handle active resource delta
>> > changes but that means that I have to introduce an editor
>> dependency > for the collection code, which I'd much rather not have,
>> or that I > have to come up with some more complex mechanism to
>> abstract this. My > thinking is that there must be some mechanism to
>> handle this already > buried in EMF somewhere...
>> How are you expecting the editor's dirty state and command stack to
>> be tracking the changes and saves you're doing in the background? It
>> seems the collection process should be kicked off as part of a
>> command and saves are done by the editor after a command finishes...
>
>
> OK, so here's the real groaner. There are a couple of issues here.. I
> need to be able to have the job run:
>
> 1. On a resource regardless of whether that resource is currently
> being viewed in an editor or not.
> 2. For performance reasons, without a command stack. (This stream is
> coming in very quickly.)
I'm not suggesting you do the changes with fine grained command, but you
must use a command or you must flush the command stack because you're
corrupted its state by making changes that make the model inconsistent
with the expected state of the stack.
> 3. (Ideally, I would use a job specific command stack where needed
> simply because I'd like to be able to reuse the ItemProvider logic and
> not have to re-implement the more complex stuff with raw ecore
> operations. But let's ignore that case for now!)
>
> My thinking was that I should simply be able to make the changes and
> then force the editor to reload the changes when it sees that an
> external change has been made. That's what the resource listener
> mechanism is for I thought.
Yes, it's for syncing up the editor with the state of the workspace if
something external changes the state there.
> Or perhaps it's just for the use of the editor loading the
> resource(s). The I guess surprising thing is that all of this worked
> until I started wanting to save the edited resource from an external
> job to the editor as well.
> Another way to put this all is that this case would work perfectly, if
> when the job was triggered, the editor stopped treating itself as an
> editor and became a viewer, i.e. a passive listener to notifications.
> Or in the least ideal case, the job would trigger the editor to close
> and then reopen it when the editing is done. Then, at the point where
> the job is finished, the token is passed back to the editor and the
> editor then becomes responsible for ensuring that the model has
> consistent state. Again, I could do this by hacking into the editor
> but I would like to avoid that. I guess I could use the Transaction
> API or CDO or something but that's the kind of overhead I don't need
> and that I'd like to avoid as well. But it is sounding like the editor
> hack is the best / only way to accomplish this.
I'm no still not totally clear on if the job is changing the actual
instance the editor is seeing or if all communication is done via the
workspace...
>
> I just realized that one neat thing I could do is actually build up
> the command stack in my external thread and then pass the whole stack
> in and feed it over to the editor command stack. I guess this is
> essentially what Transactions does anyway. That would still require
> some mechanism to discover the active editor or create a domain
> manually if an editor didn't exist, but it would have some great
> advantages as it would allow me to break things up, handle multiple
> streams, drop bad streams, etc.. but again, I worry about the
> overhead. I guess I could always implement a bunch of commands that
> don't use any of the EMF reflection / feature stuff and simply execute
> a whole set of API changes I pass in. And I could do that with
> arbitrary granularity so that I could queue up a bunch of changes in
> one whopper of a command. Have you seen anything like that implemented?
A ChangeCommand will record all changes so that your logic itself
doesn't have to worry about the fact it's being executed as part of a
command. The transaction framework has the analogous thing as well...
>
> thanks,
>
> Miles


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: Editor Unloading, Concurrency and Persistence [message #535357 is a reply to message #535333] Sat, 22 May 2010 18:01 Go to previous messageGo to next message
Miles Parker is currently offline Miles ParkerFriend
Messages: 1341
Registered: July 2009
Senior Member
Ed Merks wrote on Sat, 22 May 2010 08:52
Miles,
> 2. For performance reasons, without a command stack. (This stream is
> coming in very quickly.)
I'm not suggesting you do the changes with fine grained command, but you
must use a command or you must flush the command stack because you're
corrupted its state by making changes that make the model inconsistent
with the expected state of the stack.
...
> My thinking was that I should simply be able to make the changes and
> then force the editor to reload the changes when it sees that an
> external change has been made. That's what the resource listener
> mechanism is for I thought.
Yes, it's for syncing up the editor with the state of the workspace if
something external changes the state there.
...
> consistent state. Again, I could do this by hacking into the editor
> but I would like to avoid that. I guess I could use the Transaction
> API or CDO or something but that's the kind of overhead I don't need
> and that I'd like to avoid as well. But it is sounding like the editor
> hack is the best / only way to accomplish this.
I'm no still not totally clear on if the job is changing the actual
instance the editor is seeing or if all communication is done via the
workspace...



It's changing an instance of the resource that it itself has loaded and adapted an editing domain for. It's the same persisted resource. And actually, I could have them share the same domain as well, which sounds like what I should be doing. But form above it seems like my basic strategy is not so wrong headed after all. Essentially, if the resources change listener is notified that there have been changes to the underlying resource, it will unload and reload itself so that the updates will be seen without having had them made through command stack. But I guess the only part that is a problem is if the editor's command stack somehow get's used in the meantime, in which case the editor will see the resource as dirty and attempt to handle a conflict. So I need to make sure that I'm not touching the command stack or if I do making sure that the editor's stack has been flushed.

Anyway, it sounds like the safest thing to do is to wrap up all of my changes in large grained sets of commands and pass them into the editor's domain if one is provided or create a new editing domain if not. Then the only issue is if someone decides to edit a resource that is already in the process of being updated, but that's an edge case that I can deal with later.

Quote:

> arbitrary granularity so that I could queue up a bunch of changes in
> one whopper of a command. Have you seen anything like that implemented?
A ChangeCommand will record all changes so that your logic itself
doesn't have to worry about the fact it's being executed as part of a
command. The transaction framework has the analogous thing as well...


Yeah, there is a record feature. The whole setup is really neat -- there are just an extraordinary number of things that are enabled by having light-weight access to all of the meta-data for every change that has occurred!

But I think since I have a really constrained set of things I'm doing it would be far more efficient to write the undo manually as well. For example, if I'm adding a bunch of objects to a container, and then modifying all of those objects in various ways it doesn't make any sense to undo all o those changes for objects that will be deleted anyway. I just need to keep track of the top-level objects I've created and create a DeleteCommand for them.
Followup -- Re: Editor Unloading, Concurrency and Persistence [message #535579 is a reply to message #535000] Mon, 24 May 2010 16:47 Go to previous messageGo to next message
Miles Parker is currently offline Miles ParkerFriend
Messages: 1341
Registered: July 2009
Senior Member
Ed et.al. (though there never seems to be an et al..) -

I think I've narrowed this down to something that isn't even really a concurrency issue. Even when I use the same shared editing domain / command stack to make my external changes to the model *and* ensure that no other process make changes at the same time, the model still finds that it is dirty and displays the conflict file dialog. Worse, it seems that the EObjects themselves are somehow detached from their parent resources in the process. So, the first time I save the model from an external job (by calling save with the default save options) everything works fine, but then the change triggers a resource change notification which then leads the editor to believe it has been changed but *not* saved and then a call to eResourse returns null, even though the domain object still has a reference to it's proxy URI.

Resource null for my.foo.SomeObject@1eebcf2d (eProxyURI: platform:/resource/MyProject/Bar.somemodel#//@someobjects.0)

I've tried flushing the command stack before calling the save but that doesn't work and looking at the internals it doesn't seem like that would be the right solution.

So the question is what if anything is the pattern for making changes to a model in an asynchronous job (we do that all the time of course with handlers and I can't see that there would be a problem with wrapping it in a Job) and then (the hard part) triggering periodic saves? Perhaps I need to be doing this in a UI thread or something?

thanks,

Miles

Re: Followup -- Re: Editor Unloading, Concurrency and Persistence [message #535592 is a reply to message #535579] Mon, 24 May 2010 18:38 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33218
Registered: July 2009
Senior Member
Miles,

Comments below.


Miles Parker wrote:
> Ed et.al. (though there never seems to be an et al..) -
>
> I think I've narrowed this down to something that isn't even really a
> concurrency issue. Even when I use the same shared editing domain /
> command stack to make my external changes to the model *and* ensure
> that no other process make changes at the same time, the model still
> finds that it is dirty and displays the conflict file dialog.
Isn't that a reflection of the state of the command stack.
> Worse, it seems that the EObjects themselves are somehow detached from
> their parent resources in the process.
Unloading the resource I guess.
> So, the first time I save the model from an external job (by calling
> save with the default save options) everything works fine, but then
> the change triggers a resource change notification which then leads
> the editor to believe it has been changed but *not* saved and then a
> call to eResourse returns null, even though the domain object still
> has a reference to it's proxy URI.
Have a close look at what calling save in the editor does. You'll need
to do exactly that. Pay particular attention to how savedResources
affects processing of the delta.
>
> Resource null for mailto:my.foo.SomeObject@1eebcf2d (eProxyURI:
> platform:/resource/MyProject/Bar.somemodel#//@someobjects.0)
>
> I've tried flushing the command stack before calling the save but that
> doesn't work and looking at the internals it doesn't seem like that
> would be the right solution.
You'll see why looking at what the editor does.
>
> So the question is what if anything is the pattern for making changes
> to a model in an asynchronous job (we do that all the time of course
> with handlers and I can't see that there would be a problem with
> wrapping it in a Job) and then (the hard part) triggering periodic
> saves? Perhaps I need to be doing this in a UI thread or something?
Best to tell the editor itself to save.
>
> thanks,
>
> Miles
>
>


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: Followup -- Re: Editor Unloading, Concurrency and Persistence [message #535596 is a reply to message #535592] Mon, 24 May 2010 19:29 Go to previous messageGo to next message
Miles Parker is currently offline Miles ParkerFriend
Messages: 1341
Registered: July 2009
Senior Member
Thanks Ed, see below..

Ed Merks wrote on Mon, 24 May 2010 14:38
Miles,

Miles Parker wrote:
> that no other process make changes at the same time, the model still
> finds that it is dirty and displays the conflict file dialog.
Isn't that a reflection of the state of the command stack.



But I can only see two scenarios here:

1. I create my own domain -- AFA the editor is concerned it is just as if one had two editors opened and had saved something in a different editor. But as the editor hasn't actually changed anything it wouldn't see a conflict.
2. They share domains. In this case, it is as if the user has made a long running involved change in the editor and then saved it -- except that I am obviously not handling the save part of that properly. But still, I'm not really getting why the editor would see that as a conflict and not inconsistent state except that I'm obviously not doing something that the editor is expecting me to do.

Quote:
> Worse, it seems that the EObjects themselves are somehow detached from
> their parent resources in the process.
Unloading the resource I guess.



Right, that makes sense, so the resource is unloading itself and then reloading itself -- which works just fine for the editor because the editor has access to both the session and the resource, but that happens after my save so that I can't reload the resource. But I don't get why the EObject can find it's resource in the editor but not elsewhere after unloading..? I'll dig into that a bit more.

Quote:
> So, the first time I save the model from an external job (by calling
> save with the default save options) everything works fine, but then
> the change triggers a resource change notification which then leads
> the editor to believe it has been changed but *not* saved and then a
> call to eResourse returns null, even though the domain object still
> has a reference to it's proxy URI.
Have a close look at what calling save in the editor does. You'll need
to do exactly that. Pay particular attention to how savedResources
affects processing of the delta.
> Resource null for mailto:my.foo.SomeObject@1eebcf2d (eProxyURI:
> platform:/resource/MyProject/Bar.somemodel#//@someobjects.0)
>
> I've tried flushing the command stack before calling the save but that
> doesn't work and looking at the internals it doesn't seem like that
> would be the right solution.
You'll see why looking at what the editor does.
>
> So the question is what if anything is the pattern for making changes
> to a model in an asynchronous job (we do that all the time of course
> with handlers and I can't see that there would be a problem with
> wrapping it in a Job) and then (the hard part) triggering periodic
> saves? Perhaps I need to be doing this in a UI thread or something?
Best to tell the editor itself to save.


Thanks for the hints. I had been playing around with the command stack (and just tried (BasicCommandStack)editingDomain.getCommandStack()).saveIsDo ne()Wink , but it's looking like I'll need to have actual access to the internal state, which I had really hoped to avoid because I don't want to have any .editor dependencies. It's looking like I'll have to handle automated file persistence in two different ways one for the case where it is an object level event user triggered event from the editor and one where it is a file level event trigerred from the workspace.

-Miles
Re: Followup -- Re: Editor Unloading, Concurrency and Persistence [message #535597 is a reply to message #535596] Mon, 24 May 2010 19:39 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33218
Registered: July 2009
Senior Member
Miles,

Of you could pass in a Runnable, or something like that, that does the
saving, so that the long running process doesn't need to know any
implementation details of how the save is done.


Miles Parker wrote:
> Thanks Ed, see below..
>
> Ed Merks wrote on Mon, 24 May 2010 14:38
>> Miles,
>>
>> Miles Parker wrote:
>> > that no other process make changes at the same time, the model
>> still > finds that it is dirty and displays the conflict file dialog.
>> Isn't that a reflection of the state of the command stack.
>
>
> But I can only see two scenarios here:
>
> 1. I create my own domain -- AFA the editor is concerned it is just as
> if one had two editors opened and had saved something in a different
> editor. But as the editor hasn't actually changed anything it wouldn't
> see a conflict.
> 2. They share domains. In this case, it is as if the user has made a
> long running involved change in the editor and then saved it -- except
> that I am obviously not handling the save part of that properly. But
> still, I'm not really getting why the editor would see that as a
> conflict and not inconsistent state except that I'm obviously not
> doing something that the editor is expecting me to do.
>
> Quote:
>> > Worse, it seems that the EObjects themselves are somehow detached
>> from > their parent resources in the process.
>> Unloading the resource I guess.
>
>
> Right, that makes sense, so the resource is unloading itself and then
> reloading itself -- which works just fine for the editor because the
> editor has access to both the session and the resource, but that
> happens after my save so that I can't reload the resource. But I don't
> get why the EObject can find it's resource in the editor but not
> elsewhere after unloading..? I'll dig into that a bit more.
>
> Quote:
>> > So, the first time I save the model from an external job (by
>> calling > save with the default save options) everything works fine,
>> but then > the change triggers a resource change notification which
>> then leads > the editor to believe it has been changed but *not*
>> saved and then a > call to eResourse returns null, even though the
>> domain object still > has a reference to it's proxy URI.
>> Have a close look at what calling save in the editor does. You'll
>> need to do exactly that. Pay particular attention to how
>> savedResources affects processing of the delta.
>> > Resource null for mailto:my.foo.SomeObject@1eebcf2d (eProxyURI:
>> > platform:/resource/MyProject/Bar.somemodel#//@someobjects.0)
>> >
>> > I've tried flushing the command stack before calling the save but
>> that > doesn't work and looking at the internals it doesn't seem like
>> that > would be the right solution.
>> You'll see why looking at what the editor does.
>> >
>> > So the question is what if anything is the pattern for making
>> changes > to a model in an asynchronous job (we do that all the time
>> of course > with handlers and I can't see that there would be a
>> problem with > wrapping it in a Job) and then (the hard part)
>> triggering periodic > saves? Perhaps I need to be doing this in a UI
>> thread or something?
>> Best to tell the editor itself to save.
>
>
> Thanks for the hints. I had been playing around with the command stack
> (and just tried
> (BasicCommandStack)editingDomain.getCommandStack()).saveIsDo ne();) ,
> but it's looking like I'll need to have actual access to the internal
> state, which I had really hoped to avoid because I don't want to have
> any .editor dependencies. It's looking like I'll have to handle
> automated file persistence in two different ways one for the case
> where it is an object level event user triggered event from the editor
> and one where it is a file level event trigerred from the workspace.
>
> -Miles


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: Followup -- Re: Editor Unloading, Concurrency and Persistence [message #535605 is a reply to message #535597] Mon, 24 May 2010 20:15 Go to previous messageGo to next message
Miles Parker is currently offline Miles ParkerFriend
Messages: 1341
Registered: July 2009
Senior Member
Ed Merks wrote on Mon, 24 May 2010 15:39
Miles,

Of you could pass in a Runnable, or something like that, that does the
saving, so that the long running process doesn't need to know any
implementation details of how the save is done.


Great minds, Ed. Just did that and it works perfectly. Lesson, don't try to hack your way around the EMF. Wink
Re: Editor Unloading, Concurrency and Persistence [message #535607 is a reply to message #535000] Mon, 24 May 2010 20:36 Go to previous messageGo to next message
Miles Parker is currently offline Miles ParkerFriend
Messages: 1341
Registered: July 2009
Senior Member
BTW, this is what I did:

      
public interface IPersist {
    public void save();
}

IPersist persistFromEditor = new IPersist() {
                    public void save() {
                        editor.getViewer().getControl().getDisplay().syncExec(new Runnable() {
                            public void run() {
                                editor.doSave(null);
                            };
                        });
                    }
                };
...


And passed in persistFromEditor to my long-running job.

I am wondering if it would be possible to make the requirement that this happen in UI thread more relaxed / fine-grained. The issue if that if the delta is really large the UI could be locked for some time -- and if there is a threading issue or something else that UI doesn't handle well then you could get some difficult to diagnose issues. Perhaps on a save just the editor would be locked (somehow) and then the notifications requiring the WorkspaceModifyOperation would be fired after that event. I guess this could cause issues for the resource sets that include dependencies across multiple open editors though...I can see where it is much more manageable to have it all tied up in one UI operation.
Re: Editor Unloading, Concurrency and Persistence [message #535705 is a reply to message #535607] Tue, 25 May 2010 10:50 Go to previous message
Ed Merks is currently offline Ed MerksFriend
Messages: 33218
Registered: July 2009
Senior Member
Miles,

Certainly some parts of the save could be done on a background thread,
but the editor's state and that of the workspace is a little tenuous
during that period...


Miles Parker wrote:
> BTW, this is what I did:
>
> public interface IPersist {
> public void save();
> }
>
> IPersist persistFromEditor = new IPersist() {
> public void save() {
>
> editor.getViewer().getControl().getDisplay().syncExec(new Runnable() {
> public void run() {
> editor.doSave(null);
> };
> });
> }
> };
> ..
>
>
> And passed in persistFromEditor to my long-running job.
>
> I am wondering if it would be possible to make the requirement that
> this happen in UI thread more relaxed / fine-grained. The issue if
> that if the delta is really large the UI could be locked for some time
> -- and if there is a threading issue or something else that UI doesn't
> handle well then you could get some difficult to diagnose issues.
> Perhaps on a save just the editor would be locked (somehow) and then
> the notifications requiring the WorkspaceModifyOperation would be
> fired after that event. I guess this could cause issues for the
> resource sets that include dependencies across multiple open editors
> though...I can see where it is much more manageable to have it all
> tied up in one UI operation.


Ed Merks
Professional Support: https://www.macromodeling.com/
Previous Topic:[Teneo] Lazy ManyToOne
Next Topic:Problem removing EMF element
Goto Forum:
  


Current Time: Wed Sep 25 22:14:13 GMT 2024

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

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

Back to the top