What triggers the service model to reload and rebuild the service implementation?
The (deffered) inner proxy reloads and triggers, when a service-method is called. It does the same as the inner-proxy of the deferred-service-model. The difference is only that it gets back into play (when unlaoded).

The unloading is triggered by a Service on which all the ServiceExtensionPoints register themselvs (dependend on circularity - I haven't checked that - at start up (prefferd) or at first access - if circularity).

The source will explain it better. The source is longer than the deffered- service but it's nearly completly the same with
two exceptions: I moved the service field out in an own Object which implements the interface ImplementationHolder.
This is that the ServiceModel gets access to the (inner) Service and the ReadWriteLock. The second difference is of course the read-locking around the call to the inner ServiceInterface methods. Maybe it's easier to start with
the ServiceModel, which is the last class here.


If javaassist doesn't make it I would still implement it using DynmicProxies. The speed-penality (I guess about 2x) is I think worth the added functionality for the uses-cases I've in mind.

Normal Java Code (not javassist):

//used for connection with ServiceModel
public interface ImplementationHolder {
        public void setService(Object impl);
        public Object getService();
        public ReadWriteLock getReadWriteLock();
}

In javaassist:

//implementation of the Holder
public class ImplementationHolderImpl impelements ImplementationHolder {
        public ServiceInterf _service;
        public ReadWriteLock _rwLock = new ReadWriteLock();
        public void setService(Object service){
                this._service = (ServiceInterface) service;
        }
        public void getService(){
                return this._service;
        }
        public ReadWriteLock getReadWriteLock(){
                return _rwLock;
        }
}

//the outer proxy
public class OuterProxy implements ServiceInterface
        private final ImplementationHolderImpl _holder;
        public OuterProxy(ImplementationHolderImpl implH){
                this._holder = implH;   }

        //sample method:
        public Object sampleM(Object arg0){
        try{
                //that's the main change to the deffered. Will only block
                //if a write is acquired and the write can only be acquired
                //if no thread runs the behind this.
                _holder._rwLock.acquireRead();          return 
_holder._service.sampleM();      
        }finally{
                _holder._rwLock.releaseRead();  }
        }
}

//deffered InnerProxy (the only innerProxy no real change to the deferred- one)
public InnterProxy implements ServiceInterface {
private final ImplementationHolderImpl _holder;
private final HotReplaceServiceModel _sModel;
public InnerProxy(ImplementaitonHolderImpl holder, HotReplaceServiceModel sm){
this._holder = holder;
this._sModel = sm;
}


        private synchronized ServiceInterface getService(){
                if(_holder._service != this)
                        return _holder._service;
                _holder._service = sModel.createImplementation();
        }

        //sample
        public Object sampleM(Object arg0){
                return getService().sampleM(arg0);
        }
}

//finally the ServiceModel (of course normal Code)

public HotReplaceServiceModel extends AbstractServiceModel {
        private Object _proxy;
        private Object _deferredInnerProxy;
        private ImplementationHolder _holder;


synchronized public Object getServiceImplementation(){
if(_proxy == null){ //proxy is only set once never released or changed and always returned
_proxy = createProxy();
//we also register here with the ManagerService
//from which the shutdown/replace can be triggered
registry.getService("hivemind.HotReplaceManager",theclass)
.register(this);
}
return _proxy;
}


        public Object createProx() //(left out circulartiy check etc
        {
                //create with javassist the ImplementationHolderImpl
                _holder = creatJavaassitHolder();

                //create the innerProxy and set is as the start-state on the Holder
                _deferredInnerProxy = createJavassistInnterProxy(_holder);
                _holder.setService(_deferredInnerProxy);
                
                //finally create the outer
                _proxy = createOuterProxy(_holder);             
        }

        //now the replace. if the argument is null than shutdown
        public void replace(ServiceImplementationConstructor const)
                throws TimeOutException
        {
                //check if anything is running at all
                if(_proxy == null)
                        return;//or throw an exception

try{ //this will give it eclusive to the current thread //(we acquire with time-out in case any readLock is dead-locked
_holder.getReadWriteLock().acquireWrite(1000);
//if we have a hot-replace we just set the new ServiceIC.
if(const != null)
//some how replace the ServiceImplentationConstructor
//we don't need synchronization because we are synchronized
//check if we are not unloaded any way
if(_holder.getService() != _deferredInnerProxy){
//do the clean-up (for this we had to hold an instance of the
// current implementation anywhere (I don't do it - there is no clean- up yet)

//!!!!!!!!!
//and now just set back the deferred proxy //the (re) loading will be done by the deffered proxy.
//This setting is even cleaner than with the deferred-proxy because //everything is locked at the moment.
_holder.setService(this._deferredInnerProxy());
}

}finally{
_holder.getReadWriteLock().releaseWrite(); }
}


        //we could also add setLocked() releaseLocked() methods which
        //would just block the service if the user wants
        //But this is more or less an invitation to dead-lock (as long
        //as we do not check for reentrance).
}

On Tue, 30 Sep 2003 08:25:07 -0400, Howard M. Lewis Ship <[EMAIL PROTECTED]> wrote:


-- Howard M. Lewis Ship Creator, Tapestry: Java Web Components http://jakarta.apache.org/tapestry http://jakarta.apache.org/commons/sandbox/hivemind/ http://javatapestry.blogspot.com

-----Original Message-----
From: Christian Essl [mailto:[EMAIL PROTECTED] Sent: Tuesday, September 30, 2003 7:28 AM
To: [EMAIL PROTECTED]
Subject: [HiveMind] New service-model hot-replace/shut-down



I'd like to suggest a new service-model, which allows to replace and/or shut-down a service-implementation at runtime. (The latest refactoring makes this much easier).


The model works basicly like the deferred-model (except that it always returns the proxy). Initially it is in the deferred state and when the first request comes it creates the implementation. Different to the deffere-model all metods are sychronized with a acquireRead() read on a read-write-lock (reads go unsychnorinzed until some one aquires the write). When the user wants to shutdown or replace the implementation, the ServiceExtensionPoint aquires the write-lock. Now all current service-method-calls can finish and furthers are blocked. Than the proxy just switches back to the deffered state and does the clean-up on the service-implementation. In case of hot-replace the ServiceExtensionPoint also replaces the ServiceImplementationConstructor. Than the write-lock is released and if a new call comes in the (new)implementation is created again.

I would say the management could happen through a special service at which all the hot-replace extension points register.

I think this allows shut-down and replace during run-time and that it is totally transparent to the whole application. I'm quite sure there are also no threading issues. As I see the only dissadvantage is that it slows down the service a bit.

It could be useful for testing and ie togehter with a timer for services which are rearly used but consume quite a lot of resources.

If there is any intrest I could try to implement such a service-model.





---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]




-- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



Reply via email to