From: Leslie P. Polzer
Subject: Atomic evaluation of semantic units
Date: 
Message-ID: <75efc0c0-3322-4d93-9399-3339dcf917a4@s12g2000prg.googlegroups.com>
Suppose a live system that is to be upgraded. The upgrade alters a
bunch of things (methods, classes).

For example:

Class A is redefined
; undefined state here
Method M(A) is redefined **

Now at the marked spot between those two redefinitions we need to
avoid calling the old method on the new class (slot semantics may have
changed for example).

How can this be avoided? Is there a way to ensure that the
redefinitions occur in an atomic way? Think

(with-upgrade-transaction
  (defclass ...
  (defmethod ...

Of course uninterning the old definitions beforehand wouldn't be
acceptable either since they might be called in the meantime.

Maybe the MOP can help?

  Leslie

From: Kaz Kylheku
Subject: Re: Atomic evaluation of semantic units
Date: 
Message-ID: <d5d43c30-8461-4232-af67-5b5bfb574db8@e23g2000prf.googlegroups.com>
On Dec 27, 4:42 am, "Leslie P. Polzer" <·············@gmx.net> wrote:
> How can this be avoided? Is there a way to ensure that the
> redefinitions occur in an atomic way?

What? That would require a big lock around all of the things being
updated.

Can you accept the performance penalties?

 Think
>
> (with-upgrade-transaction
>   (defclass ...
>   (defmethod ...

Anyone using that class or method would have to acquire the same lock
that is used by WITH-UPGRADE-TRANSACTION.

What's worse can't necessarily predict which subsets of classes,
methods or other symbols might be included in a given transaction. In
the worst case, you might want to upgrade everything atomically.

This means having a big, global lock around the use of everything.

There is such a thing as too high a price to pay for atomicity.
From: Peder O. Klingenberg
Subject: Re: Atomic evaluation of semantic units
Date: 
Message-ID: <ks63ykwbf3.fsf@beto.netfonds.no>
"Leslie P. Polzer" <·············@gmx.net> writes:

> How can this be avoided? Is there a way to ensure that the
> redefinitions occur in an atomic way? Think

If your implementation is multithreaded, the multithreading library
will probably support something like a WITHOUT-INTERRUPTS macro.  If
it's not multithreaded, you don't have a problem, of course.

...Peder...
-- 
This must be Thursday.  I never could get the hang of Thursdays.
From: Alex Mizrahi
Subject: Re: Atomic evaluation of semantic units
Date: 
Message-ID: <47740ec2$0$90273$14726298@news.sunsite.dk>
 LPP> Now at the marked spot between those two redefinitions we need to
 LPP> avoid calling the old method on the new class (slot semantics may have
 LPP> changed for example).

we need to avoid calling *anything* during upgrade process if we want really 
safe upgrade, because we can have current execution stuff incompatible with 
new method or class definitions.
a "big lock" around your main processing code and upgrade procedure will 
help.
so you stop all your processing (finishing stuff you're doing and not 
starting new stuff), then upgrade, then start processing again.

in case of multithreaded server something like read-write lock is needed --  
lock for reading when you do processing, lock for writing when you do 
upgrade.

 LPP> Maybe the MOP can help?

if few seconds (while upgrade goes) of downtime is not acceptable to you, 
the only way would be limiting changes you're making to ensure they are not 
breaking anything.
analyzing stuff for race-condition safety during upgrades is pretty complex, 
so i think it's better to use two servers if you cannot tolerate delays :).
From: D Herring
Subject: Re: Atomic evaluation of semantic units
Date: 
Message-ID: <a_ydnbgDXNTIHOnanZ2dnUVZ_qygnZ2d@comcast.com>
Leslie P. Polzer wrote:
> Suppose a live system that is to be upgraded. The upgrade alters a
> bunch of things (methods, classes).
> 
> For example:
> 
> Class A is redefined
> ; undefined state here
> Method M(A) is redefined **
> 
> Now at the marked spot between those two redefinitions we need to
> avoid calling the old method on the new class (slot semantics may have
> changed for example).
> 
> How can this be avoided? Is there a way to ensure that the
> redefinitions occur in an atomic way? Think
> 
> (with-upgrade-transaction
>   (defclass ...
>   (defmethod ...
> 
> Of course uninterning the old definitions beforehand wouldn't be
> acceptable either since they might be called in the meantime.
> 
> Maybe the MOP can help?

Probably not; more than just threading issues here; how to cleanly 
upgrade all instances of the redefined class, etc.

If you need to do this seamlessly, it will probably look something 
like this:
- start up new code running parallel to old code
- if necessary, use a back channel to synchronize the code bases
- have the new code accept all new connections
- instruct the old code to stop accepting new connections
- when the old connections complete or timeout, shut down the old code

If you don't need complete transparency, WITH-UPGRADE-TRANSACTION 
would look like
- have the old code stop communicating with the outside world
- load in the new definitions; upgrade all old class instances
- restart communication

This is one thing the unix filesystem got right (and MS botched): 
files are unlinked and then garbage collected -- programs shouldn't 
have to close the file before it can be deleted or overwritten.  Same 
thing goes for software upgrades.

Later,
Daniel

Disclaimer:  I've never done this with a real system; my opinions are 
based on experience with lock-free algorithms.