Beginner question: Restoring of state after image save and restart of Dolphin

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Beginner question: Restoring of state after image save and restart of Dolphin

Bernhard Kohlhaas
Hello all,

I used to work with Parkplace Smalltalk for a few months about ten years
ago, but even after all this abstinence I had a "relapse" ;) and
recently bought the Dolphin Value Edition 5.1 to work on some personal
projects. :)

One of the first classes I wrote was a "DirectoryChangeWatcher", whose
instances monitor for a given directory (and optionally its subdirs) all
changes that occur. I implemented this by forking a process and
performint an overlapped external call to ReadDirectoryChangesW.
Most of the time of course that forked process blocks on the external call.

This works fine, but what I am wondering about is how to deal with an
image save and restart of Smalltalk. (So far I haven't tried to save
an image when an instance of DirectoryChangeWatcher was still around).
Will the image save properly (even with a process blocked on an
overlapped external call) and if so, what state will the image be when
I restart Smalltalk? Will that forked process be still alive or do I
need to terminate it and start a new one?

If I need to start a new one (or perform some action before and after
the image save), what is the protocol to adhere to)?
After browsing the SessionManager class hiearchy, it seems that I need
to register with "SessionManager current" for the events
#sessionStarted, #imageSaveStarting and #imageSaveCompleted. Is that the
recommended way or is there another protocol to handle this?


Last but not least on what "level" of the application should I handle
this? I.e. should every low-level class be able to reinstate their
former state after the restart of an image? In that case I would have
expected some coding in the File class to "OnStartup" reopen any file.

Or should those things rather be handled on a higher application level,
i.e. the main application has to invalid and reinstantiate all lower
level objects (i.e. instances of File)?

Thank you very much for any insights into the matter,

Bernhard


Reply | Threaded
Open this post in threaded view
|

Re: Beginner question: Restoring of state after image save and restart of Dolphin

Blair McGlashan
"Bernhard Kohlhaas" <[hidden email]> wrote in message
news:[hidden email]...
> ...
> One of the first classes I wrote was a "DirectoryChangeWatcher", whose
> instances monitor for a given directory (and optionally its subdirs) all
> changes that occur. I implemented this by forking a process and
> performint an overlapped external call to ReadDirectoryChangesW.
> Most of the time of course that forked process blocks on the external
call.
>
> This works fine, but what I am wondering about is how to deal with an
> image save and restart of Smalltalk. (So far I haven't tried to save
> an image when an instance of DirectoryChangeWatcher was still around).
> Will the image save properly (even with a process blocked on an
> overlapped external call) and if so, what state will the image be when
> I restart Smalltalk? Will that forked process be still alive or do I
> need to terminate it and start a new one?

The image will certainly save properly, but since the state of the
overlapped call cannot be known (in general) when the image is saved, it
isn't possible to "restore" it on correctly on restart. We did consider
re-initiating the overlapped call on image restart, but reasoned that the
times when this would work did not justify the risk of it carrying out some
undesired action. Also because external calls are frequently used in
conjunction with external resources, it seemed quite likely that the
arguments to the call itself would be invalid on image restart. Therefore
the call has to be re-initiated (if required) from a higher level.

So what you will find is that the Process will be there blocked on the same
Semaphore that it was when the image was saved. This is the overlapped call
completion Semaphore, which will never get signalled unless explicitly from
the "application".

In D5 the Semaphore is referenced from the 'overlappedCalls' instance
variable of the Processor global, and is the single Semaphore used to block
pending overlapped calls. However this is an implementation detail that
should not be relied upon because it has been changed for D6. In D5 the
single Semaphore is replaced with a new one on image restart (see
ProcessorScheduler>>onStartup:), and so unless the process' blocked upon it
are referenced from elsewhere, or the Semaphore itself is referenced from
elsewhere, then it and the blocked process' will probably be GC'd shortly
after image startup.

> If I need to start a new one (or perform some action before and after
> the image save), what is the protocol to adhere to)?
> After browsing the SessionManager class hiearchy, it seems that I need
> to register with "SessionManager current" for the events
> #sessionStarted, #imageSaveStarting and #imageSaveCompleted. Is that the
> recommended way or is there another protocol to handle this?
>

You probably want to observe #sessionStarted and #sessionStopped. The image
save events are less useful than they might at first appear, because one
generally doesn't want to upset the state of the image on image save as it
has to keep running exactly as before afterwards.

>
> Last but not least on what "level" of the application should I handle
> this? I.e. should every low-level class be able to reinstate their
> former state after the restart of an image? In that case I would have
> expected some coding in the File class to "OnStartup" reopen any file.

Well that is a design decision as to which there is no one right answer. In
fact you may decide not to bother reinstating the state of certain objects
at all because the convenience does not justify the effort in doing so, or
perhaps because the "world" may not be the same when the image is restarted,
and so it does not make sense, or is not safe, to restore everything as it
was. We do not make any attempt to restore Files.

In general though we do try and preserve the illusion that the image will
start up everything as it was before, and quite often this is done by
observing the SessionManager events. However we typically try and restore
external resources lazily - this avoids both unecessarily lengthening
startup times, and also consuming external resources that are not actually
needed in the new session.

We found it such a common pattern that one should have an object that held
an ExternalHandle for some external resource, and that we had startup
processing to go through and nil these out so that they could be lazily
recreated later, that we modified the VM's image loading code such that it
automatically nulls out all instances of ExternalHandle (i.e. it sets the
value of the instances to zero, rather than nilling out references to
external handles). I think this change was made in D4, and the result is
that many classes wrapping external resources no longer need special session
startup code as long as they protect access to the resource handle with an
accessor method that lazily creates the class based on an #isNull test
against the handle.

>
> Or should those things rather be handled on a higher application level,
> i.e. the main application has to invalid and reinstantiate all lower
> level objects (i.e. instances of File)?
>

As to the level at which you should restore the state, well my preference is
to do this at the lowest level at which you have all the information
available to be able to do it. Typically the object which owns an external
resource should be responsible for restoring in on image reload. However if
that object is a private implementation detail that is not part of the
public interface of the higher-level class, it would be reasonable to
discard it and create a new one in the higher level object. Another reason
to do the state restoral in higher layers would be where on needs to deal
with possible changes in the world outside the image since it was last
running.

Regards

Blair


Reply | Threaded
Open this post in threaded view
|

Re: Beginner question: Restoring of state after image save and restart of Dolphin

Bernhard Kohlhaas
Blair McGlashan wrote:
[...]
> The image will certainly save properly, but since the state of the
> overlapped call cannot be known (in general) when the image is saved, it
> isn't possible to "restore" it on correctly on restart. We did consider
> re-initiating the overlapped call on image restart, but reasoned that the
> times when this would work did not justify the risk of it carrying out some
> undesired action. Also because external calls are frequently used in
> conjunction with external resources, it seemed quite likely that the
> arguments to the call itself would be invalid on image restart. Therefore
> the call has to be re-initiated (if required) from a higher level.

That makes certainly sense, since in my case a valid file handle is
needed for the call.

[Observing SessionManager events...]

> You probably want to observe #sessionStarted and #sessionStopped. The image
> save events are less useful than they might at first appear, because one
> generally doesn't want to upset the state of the image on image save as it
> has to keep running exactly as before afterwards.

What would be the benefit of observing #sessionStopped ? Usually I'd
close all external resources in the #finalize method. Or is finalization
not invoked during image shutdown? In that case I'd of course have to
close all external resources that Windows doesn't close automatically
(or to my liking) when a program terminates.

[...]

Thanks so much, Blair for your explanations of Dolphin's behavior and
the reflections on the best programming practices. It's not only the
level of expertise, but also the level of helpfulness, that makes this
newsgroup so impresssive. :)

Best Regards,
Bernhard