Package org.rioproject.impl.sla

Source Code of org.rioproject.impl.sla.RelocationPolicyHandler

/*
* Copyright 2008 the original author or authors.
* Copyright 2005 Sun Microsystems, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.rioproject.impl.sla;

import com.sun.jini.proxy.BasicProxyTrustVerifier;
import net.jini.export.Exporter;
import net.jini.jeri.BasicILFactory;
import net.jini.jeri.BasicJeriExporter;
import net.jini.jeri.tcp.TcpServerEndpoint;
import net.jini.security.TrustVerifier;
import net.jini.security.proxytrust.ServerProxyTrust;
import org.rioproject.impl.config.ExporterConfig;
import org.rioproject.servicebean.ServiceBeanContext;
import org.rioproject.deploy.ServiceBeanInstance;
import org.rioproject.deploy.ServiceProvisionListener;
import org.rioproject.event.EventHandler;
import org.rioproject.opstring.ServiceElement;
import org.rioproject.sla.SLA;
import org.rioproject.watch.Calculable;
import org.rioproject.impl.watch.ThresholdManager;
import org.rioproject.watch.ThresholdType;
import org.rioproject.watch.ThresholdValues;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.rmi.RemoteException;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

/**
* The RelocationPolicyHandler will inform the OperationalStringManager to
* relocate the ServiceBean that uses this policy handler. The
* RelocationPolicyHandler will look for attributes set that can control it's
* operational behavior.
* <p>
* The <span style="font-family: monospace;">RelocationPolicyHandler </span>
* supports the following configuration entries; where each configuration entry
* name is associated with the component name <span style="font-family:
* monospace;">relocationPolicyHandler </span> <br>
*
* <ul>
* <li><span style="font-weight: bold; font-family: courier
* new,courier,monospace;">provisionListenerExporter </span> <br
* style="font-family: courier new,courier,monospace;"> <table cellpadding="2"
* cellspacing="2" border="0" style="text-align: left; width: 100%;"> <tbody>
* <tr><td style="vertical-align: top; text-align: right; font-weight:
* bold;">Type: <br>
* </td>
* <td style="vertical-align: top;">Exporter</td>
* </tr>
* <tr><td style="vertical-align: top; text-align: right; font-weight:
* bold;">Default: <br>
* </td>
* <td style="vertical-align: top;">A new <code>BasicJeriExporter</code> with
* <ul>
* <li>a <code>TcpServerEndpoint</code> created on a random port,</li>
* <li>a <code>BasicILFactory</code>,</li>
* <li>distributed garbage collection turned off,</li>
* <li>keep alive on.</li>
* </ul>
* <code></code></td>
* </tr>
* <tr><td style="vertical-align: top; text-align: right; font-weight:
* bold;">Description: <br>
* </td>
* <td style="vertical-align: top;">The Exporter used to export the
* ProvisionListener server. A new exporter is obtained every time a
* RelocationPolicyHandler needs to export itself.</td>
* </tr>
* </tbody> </table></li>
* </ul>
* <span style="font-weight: bold; font-family: courier new,courier,monospace;">
* <br>
* </span>
*
* @author Dennis Reedy
*/
public class RelocationPolicyHandler extends SLAPolicyHandler
        implements
            ServiceProvisionListener,
            ServerProxyTrust {
    /** The description of the SLA Handler */
    private static final String description = "Relocation Policy Handler";
    /** Dampening value for upper thresholds being crossed */
    private long upperThresholdDampeningTime;
    /** Dampening value for lower thresholds being crossed */
    private long lowerThresholdDampeningTime;
    /** The Timer to use for scheduling a relocation task */
    private Timer taskTimer;
    /** The RelocationTask for incrementing */
    private RelocationTask relocationTask;
    /** Action that indicates an relocation request is pending */
    public static final String RELOCATION_PENDING = "RELOCATION_PENDING";
    /** Action that indicates an relocation request has failed */
    public static final String RELOCATION_FAILURE = "RELOCATION_FAILURE";
    /**
     * Action that indicates an relocation request has succeeded. The resultant
     * Object in the SLAPolicyEvent will be the proxy of the new service
     */
    public static final String RELOCATION_SUCCEEDED = "RELOCATION_SUCCEEDED";
    /** The remote ref (e.g. stub or dynamic proxy) */
    private Object ourRemoteRef;
    /** The Exporter */
    private Exporter exporter;
    /** Component name */
    private static final String CONFIG_COMPONENT = "relocationPolicyHandler";
    /** Logger for this component */
    static Logger logger = LoggerFactory.getLogger("org.rioproject.sla");

    /**
     * Construct a RelocationPolicyHandler
     *
     * @param sla The SLA for the RelocationPolicyHandler
     */
    public RelocationPolicyHandler(SLA sla) {
        super(sla);
        taskTimer = new Timer(true);
    }

    /**
     * Override parent's method to return description for this SLA Handler
     *
     * @return The descriptive attribute for this SLA Handler
     */
    @Override
    public String getDescription() {
        return (description);
    }

    /**
     * Override parent's method to export the object to the RMI runtime
     */
    @Override
    public void setThresholdManager(ThresholdManager thresholdManager) {
        if(ourRemoteRef==null)
            exportDo();
        super.setThresholdManager(thresholdManager);
    }

    /**
     * Override parent's method to unexport
     */
    @Override
    public void disconnect() {
        try {
            exporter.unexport(true);
        } catch(IllegalStateException e) {
            if(logger.isTraceEnabled())
                logger.trace("RelocationPolicyHandler unexport failed", e);
        }
        ourRemoteRef = null;
        if(taskTimer != null)
            taskTimer.cancel();
        super.disconnect();
    }

    /**
     * Override parent's initialize method to initialize operational attributes
     */
    @Override
    public void initialize(Object eventSource,
                           EventHandler eventHandler,
                           ServiceBeanContext context) {
        super.initialize(eventSource, eventHandler, context);
        if(exporter==null) {
            try {
                exporter = ExporterConfig.getExporter(getConfiguration(),
                                                      CONFIG_COMPONENT,
                                                      "provisionListenerExporter");

            } catch(Exception e) {
                logger.warn("Getting provisionListenerExporter, use default", e);
            }
            /* If we still dont have an exporter create a default one */
            if(exporter==null) {
                exporter = new BasicJeriExporter(TcpServerEndpoint.getInstance(0),
                                                 new BasicILFactory(),
                                                 false,
                                                 true);
            }
        }
        try {
            upperThresholdDampeningTime =
                (getSLA().getUpperThresholdDampeningTime()==0?1000:
                    getSLA().getUpperThresholdDampeningTime());

            lowerThresholdDampeningTime =
                (getSLA().getLowerThresholdDampeningTime()==0?1000:
                    getSLA().getLowerThresholdDampeningTime());

            if(logger.isDebugEnabled()) {
                logger.debug("["+context.getServiceElement().getName()+"] "+
                            "RelocationPolicyHandler ["+getID()+"]: properties, "+
                            "low Threshold="+getSLA().getLowThreshold()+", "+
                            "high Threshold="+getSLA().getHighThreshold()+", "+
                            "upperThresholdDampeningTime="+upperThresholdDampeningTime+", "+
                            "lowerThresholdDampeningTime="+lowerThresholdDampeningTime);
            }
        } catch(Exception e) {
            logger.error("Getting Operational Configuration", e);
        }
    }

    /**
     * @see org.rioproject.impl.watch.ThresholdListener#notify
     */
    @Override
    public void notify(Calculable calculable, ThresholdValues thresholdValues, ThresholdType type) {
        if(logger.isDebugEnabled()) {
            String status = type.name().toLowerCase();
            logger.debug("RelocationPolicyHandler [" + getID() + "]: Threshold ["
                        + calculable.getId() + "] " + status + " value ["
                        + calculable.getValue() + "\n] low ["
                        + thresholdValues.getCurrentLowThreshold() + "]" + " high ["
                        + thresholdValues.getCurrentHighThreshold() + "]");
        }
        if(type == ThresholdType.BREACHED) {
            double tValue = calculable.getValue();
            if(tValue > thresholdValues.getCurrentHighThreshold()) {
                fireRelocation(upperThresholdDampeningTime, "upper");
            } else {
                fireRelocation(lowerThresholdDampeningTime, "lower");
            }

        /* Threshold has been cleared */
        } else {
            if(relocationTask!=null) {
                relocationTask.cancel();
                relocationTask = null;
            }
        }
        sendSLAThresholdEvent(calculable, thresholdValues, type);
    }

    /*
     * Determine whether a RelocationTask should be created based on the
     * dampening value provided, or to relocate immediately
     */
    void fireRelocation(long dampener, String type) {
        if(dampener > 0) {
            relocationTask = new RelocationTask();
            long now = System.currentTimeMillis();
            if(logger.isDebugEnabled())
                logger.debug("["+context.getServiceElement().getName()+"] "+
                            "RelocationPolicyHandler ["+getID()+"]: "+
                            "Schedule relocation task in "+
                            "["+dampener+"] millis");
            try {
                taskTimer.schedule(relocationTask,
                                   new Date(now+ dampener));
            } catch(IllegalStateException e) {
                logger.warn("Force disconnect of "+
                           "["+context.getServiceElement().getName()+"] "+
                           "RelocationPolicyHandler",
                           e);
                disconnect();
            }
        } else {
            if(logger.isDebugEnabled())
                logger.debug("["+context.getServiceElement().getName()+"] "+
                            "RelocationPolicyHandler ["+getID()+"]: "+
                            "no "+type+" dampener, perform relocation");
            doRelocate();
        }
    }

    /**
     * @see org.rioproject.deploy.ServiceProvisionListener#succeeded
     */
    public void succeeded(ServiceBeanInstance jsbInstance)
    throws RemoteException {
        try {
            notifyListeners(new SLAPolicyEvent(this,
                                               getSLA(),
                                               RELOCATION_SUCCEEDED,
                                               jsbInstance.getService()));
        } catch(Exception e) {
            logger.warn("Getting service to create SLAPolicyEvent", e);
        }
    }

    /**
     * @see org.rioproject.deploy.ServiceProvisionListener#failed
     */
    public void failed(ServiceElement sElem, boolean resubmitted)
    throws RemoteException {
        notifyListeners(new SLAPolicyEvent(this, getSLA(), RELOCATION_FAILURE));
    }

    /**
     * Returns a <code>TrustVerifier</code> which can be used to verify that a
     * given proxy to this policy handler can be trusted
     */
    public TrustVerifier getProxyVerifier() {
        if(ourRemoteRef==null)
            exportDo();
        return (new BasicProxyTrustVerifier(ourRemoteRef));
    }
   
    /**
     * Export the RelocationPolicyHandler
     */
    private void exportDo() {
        try {           
            ourRemoteRef = exporter.export(this);
        } catch(RemoteException e) {
            logger.error(
                       "Exporting RelocationPolicyHandler ["+getID()+"]",
                       e);
        }
    }

    /**
     * Perform the relocation
     */
    void doRelocate() {
        notifyListeners(new SLAPolicyEvent(this,
                                           getSLA(),
                                           RELOCATION_PENDING));
        try {
            if(ourRemoteRef == null)
                exportDo();
           
            context.getServiceBeanManager().relocate(
                (ServiceProvisionListener)ourRemoteRef,
                null);              
        } catch(Exception e) {
            if(!logger.isTraceEnabled()) {
                logger.warn("Attempt to invoke relocate method on " +
                               "ProvisionManager ["+
                               e.getClass().getName()+" : "+
                               e.getLocalizedMessage()+"]");
            } else {
                logger.warn(
                           "Attempt to invoke relocate method on ProvisionManager",
                           e);
            }
            notifyListeners(new SLAPolicyEvent(this,
                                               getSLA(),
                                               RELOCATION_FAILURE));
        }
    }

    /**
     * The RelocationTask is used to schedule a relocation be performed at
     * some time in the future.
     */
    class RelocationTask extends TimerTask {

        public void run() {
            doRelocate();
        }
    }
}
TOP

Related Classes of org.rioproject.impl.sla.RelocationPolicyHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.