Package com.ericsson.ssa.container.overload

Source Code of com.ericsson.ssa.container.overload.OverloadProtectionManager

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
* Copyright (c) Ericsson AB, 2004-2008. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License").  You
* may not use this file except in compliance with the License. You can obtain
* a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code.  If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [year]
* [name of copyright owner]"
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license."  If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above.  However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package com.ericsson.ssa.container.overload;

import com.sun.enterprise.admin.event.AdminEventListenerException;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.naming.NamingException;

import org.glassfish.comms.api.overload.OverloadNotifier;
import org.glassfish.comms.api.overload.OverloadDetectionRegistrar;
import org.glassfish.comms.api.overload.OverloadEvent;
import org.glassfish.comms.api.overload.OverloadListener;
import org.glassfish.comms.api.overload.OverloadEvent.TrafficType;
import org.jvnet.glassfish.comms.httplayers.HttpLayer;
import org.jvnet.glassfish.comms.util.LogUtil;

import com.ericsson.ssa.config.ConfigFactory;
import com.ericsson.ssa.config.annotations.Configuration;
import com.ericsson.ssa.container.OverloadManager;
import com.ericsson.ssa.container.reporter.Reporter;
import com.ericsson.ssa.container.reporter.ReporterResolver;
import com.ericsson.ssa.sip.Layer;
import com.ericsson.ssa.sip.LayerHelper;
import com.ericsson.ssa.sip.SipServletRequestImpl;
import com.ericsson.ssa.sip.SipServletResponseImpl;
import com.sun.enterprise.NamingManager;
import com.sun.enterprise.Switch;
import com.sun.enterprise.config.ConfigContext;
import com.sun.enterprise.config.serverbeans.Config;
import com.sun.enterprise.config.serverbeans.ServerBeansFactory;
import com.sun.enterprise.server.ServerContext;
import com.sun.grizzly.tcp.Request;
import com.sun.grizzly.tcp.Response;

public class OverloadProtectionManager implements OverloadListener,
    OverloadConfiguration, Layer, HttpLayer {
  private static final Logger LOGGER = LogUtil.SIP_LOGGER.getLogger();
  private static OverloadProtectionManager _singletonInstance = new OverloadProtectionManager();
  private Set<String> isInitialOverload = new HashSet<String>();
  private Set<String> isSubsequentOverload = new HashSet<String>();
  private Set<String> isHttpOverload = new HashSet<String>();
  private Set<String> isMaxOverload = new HashSet<String>();
  private Layer _nextLayer = null;
  protected OverloadSampler os;
  // private String _hostName = "";
  private Reporter _reporter;
        private static final int HTTP_MAX_OVERLOAD_STATUS_CODE = -1;              
       
  protected OverloadProtectionManager() {
  }

  public static OverloadProtectionManager getInstance() {
    if (shouldInsertOLPM()) {
      return _singletonInstance;
    } else {
      return null;
    }
  }

  private static boolean shouldInsertOLPM() {          
            boolean newolpenabled = false;
            ServerContext sc =
                    com.sun.enterprise.server.ondemand.OnDemandServer.getServerContext();
            ConfigContext instanceConfigContext = sc.getConfigContext();
            Config instanceConfig = null;
            try {
                instanceConfig =
                        (Config) ServerBeansFactory.getConfigBean(instanceConfigContext);
                if (instanceConfig.getOverloadProtectionService() != null) {
                    newolpenabled = instanceConfig.getOverloadProtectionService().
                            isEnabled();
                }
            } catch (Exception ex) {
                ;
            }
            boolean oldolpenabled = "true".equals(ConfigFactory.getConfig().get("/SipContainer",
        "olpInserted"));
            return oldolpenabled || newolpenabled;
  }       

  /**
   * @see getInstance
   * @return the singleton
   */
  public static HttpLayer getHttpLayerInstance() {
    if (shouldInsertOLPM()) {
      return _singletonInstance;
    } else {
      return null;
    }
  }

  /**
   * Starts the overload protection.
   */
  public synchronized void start() {
    if (LOGGER.isLoggable(Level.FINE)) {
      LOGGER.log(Level.FINE, "Started OverloadProtection.");
    }
    os = new OverloadSampler(this);
    os.start();
    os.addListener(this);
    publishJNDI();
                OverloadJMXNotifier.start();         
  }

  /**
   * Stops the overload protection.
   */
  public synchronized void stop() {
    if (LOGGER.isLoggable(Level.FINE)) {
      LOGGER.log(Level.FINE, "Stopped OverloadProtection");
    }
    os.stop();
    os.removeListener(this);
                OverloadJMXNotifier.stop();
    os = null;               
  }

  protected synchronized void publishJNDI() {
    try {
      NamingManager namingManager = Switch.getSwitch().getNamingManager();

      String jndiName1 = OverloadNotifier.class.getName();
      if (LOGGER.isLoggable(Level.FINER)) {
        LOGGER.log(Level.FINER, "Publishing the object " + jndiName1);
      }
      Object o1 = OverloadFactoryImpl.newInstance(jndiName1,
          org.glassfish.comms.api.overload.OverloadNotifier.class);
      namingManager.publishObject(jndiName1, o1, true);

      String jndiName2 = OverloadDetectionRegistrar.class.getName();
      if (LOGGER.isLoggable(Level.FINER)) {
        LOGGER.log(Level.FINER, "Publishing the object " + jndiName2);
      }
      Object o2 = OverloadFactoryImpl
          .newInstance(
              jndiName1,
              org.glassfish.comms.api.overload.OverloadDetectionRegistrar.class);
      namingManager.publishObject(jndiName2, o2, true);
    } catch (NamingException ne) {
      ne.printStackTrace();
    }
  }
 

  /**
   * Accessed by JNDI
   *
   * @return
   */
  OverloadSampler getJNDIAccess() {
    return os;
  }

  public void activate(Object configurable) {
    ConfigFactory.instance().activateConfiguration(configurable);
  }

  public void deactivate(Object configurable) {
    ConfigFactory.instance().deactivateConfiguration(configurable);
  }

  public synchronized void raiseInitialOverload(String type) {
    this.isInitialOverload.add(type);
  }

  public synchronized void ceaseInitialOverload(String type) {
    this.isInitialOverload.remove(type);
  }

  public synchronized void raiseSubsequentOverload(String type) {
    this.isSubsequentOverload.add(type);
  }

  public synchronized void ceaseSubsequentOverload(String type) {
    this.isSubsequentOverload.remove(type);
  }

  private synchronized void raiseHttpOverload(String type) {
    this.isHttpOverload.add(type);
  }

  private synchronized void ceaseHttpOverload(String type) {
    this.isHttpOverload.remove(type);
  }

  public synchronized void raiseMaxOverload(String type) {
    this.isMaxOverload.add(type);
  }

  private synchronized void ceaseMaxOverload(String type) {
    this.isMaxOverload.remove(type);
  }

  public void dispatch(SipServletRequestImpl req) {
    req.popDispatcher().dispatch(req);
  }

  public void dispatch(SipServletResponseImpl resp) {
    resp.peekDispatcher().dispatch(resp);
  }

  public boolean invoke(final Request request, final Response response)
      throws Exception {
    if (isMaxOverload()) {
      if (LOGGER.isLoggable(Level.FINE)) {
        LOGGER.log(Level.FINE,
            "Method invoke: Max load, drop all http messages");
                        }
                        if (os.getMmThresholdHttpWaitTime() >= 0){
                            /*
                             * Contract between OLP and http proxy.
                             * Status code of -1 indicates max overload
                             * and the wait time for the thread is conveyed
                             * through the message.
                             */
                            response.setStatus(HTTP_MAX_OVERLOAD_STATUS_CODE);
                            response.setMessage("" +
                                    os.getMmThresholdHttpWaitTime());                                 
                        } else {
                            /*
                             * If the wait time is configured as -1
                             * we fall back to the old behavior of sending
                             * a 503.
                             */
                            response.setStatus(503);
          setRetryAfter(response, TrafficType.HTTP);
                        }
                        incrEasOverloadRejectedHttpRequests(TrafficType.ALL);
      return false;
    } else if (isHttpOverload()) {
      if (LOGGER.isLoggable(Level.FINE)) {
        LOGGER.log(Level.FINE,
            "Method invoke: isOverloadHttp, return 503");
      }                       
      response.setStatus(503);
      setRetryAfter(response, TrafficType.HTTP);
      incrEasOverloadRejectedHttpRequests(TrafficType.HTTP);
      return false;
    }

    return true;
  }

  public void onDestroy() {
    // TBD
  }

  public Reporter getReporter() {
    return _reporter;
  }

  private synchronized boolean isMaxOverload() {
    return !isMaxOverload.isEmpty();
  }

  private synchronized boolean isInitialOverload() {
    return !isInitialOverload.isEmpty();
  }

  private synchronized boolean isSubsequentOverload() {
    return !isSubsequentOverload.isEmpty();
  }

  private synchronized boolean isHttpOverload() {
    return !isHttpOverload.isEmpty();
  }

  public void next(final SipServletRequestImpl req) {
    if (isMaxOverload()) {
      if (LOGGER.isLoggable(Level.FINE)) {
        LOGGER.log(Level.FINE, "Max load, drop all sip requests");
      }

      incrEasOverloadRejectedSipRequests(TrafficType.ALL, req.getMethod());
      return;
    }

    if (req.isInitial()) {
      if (isInitialOverload()) {
        SipServletResponseImpl resp = req
            .createTerminatingResponse(503);

        setRetryAfter(resp, TrafficType.SIP_INITIAL);

        if (LOGGER.isLoggable(Level.FINE)) {
          LOGGER
              .log(Level.FINE,
                  "Method next (req): rejecting initial request with 503");
        }
        incrEasOverloadRejectedSipRequests(TrafficType.SIP_INITIAL, req
            .getMethod());

        if (resp != null) {
          resp.popDispatcher().dispatch(resp);
        }

        return;
      }
    } else {
      // lets handle ACK as an initial request, it's a risk otherwise
      // that INVITE is stopped but ACK is sent to next layer...
      if (req.getMethod().equals("ACK")) {
        if (isInitialOverload()) {
          // drop ACK
          if (LOGGER.isLoggable(Level.FINE)) {
            LOGGER.log(Level.FINE,
                "Method next (req): dropping ACK ");
          }
          incrEasOverloadRejectedSipRequests(
              TrafficType.SIP_SUBSEQUENT, req.getMethod());

          return;
        }
      } else if (isSubsequentOverload()) {
        SipServletResponseImpl resp = req
            .createTerminatingResponse(503);
        setRetryAfter(resp, TrafficType.SIP_SUBSEQUENT);

        if (LOGGER.isLoggable(Level.FINE)) {
          LOGGER
              .log(Level.FINE,
                  "Method next (req): rejecting subsequent request with 503");
        }
        incrEasOverloadRejectedSipRequests(TrafficType.SIP_SUBSEQUENT,
            req.getMethod());

        if (resp != null) {
          resp.popDispatcher().dispatch(resp);
        }

        return;
      }
    }

    LayerHelper.next(req, this, _nextLayer);
  }

  public void next(final SipServletResponseImpl resp) {
    if (isMaxOverload()) {
      if (LOGGER.isLoggable(Level.FINE)) {
        LOGGER.log(Level.FINE, "Method next (resp):"
            + "Max load, drop all sip responses");
      }

      return;
    }

    LayerHelper.next(resp, this, _nextLayer);
  }

  protected void setRetryAfter(SipServletResponseImpl resp,
      TrafficType trafficType) {
    resp.setHeader("Retry-After", String
        .valueOf(os.retryAfter(trafficType)));
  }

  protected void setRetryAfter(Response resp, TrafficType trafficType) {
    resp.addHeader("Retry-After", String
        .valueOf(os.retryAfter(trafficType)));
  }

  protected void incrEasOverloadRejectedSipRequests(TrafficType trafficType,
      String method) {
    OverloadManager.getInstance().incrEasOverloadRejectedSipRequests();
  }

  protected void incrEasOverloadRejectedHttpRequests(TrafficType trafficType) {
    OverloadManager.getInstance().incrEasOverloadRejectedHttpRequests();
  }

  public void registerNext(final Layer layer) {
    _nextLayer = layer;
  }

  public void setReporters(String reporters) {
    _reporter = ReporterResolver.getInstance().getReporter(reporters);
  }

  /**
   * @return info
   */
  public String getInfo() {
    return "Overload Regulation";
  }

  public void ceaseOverload(OverloadEvent e) {
    switch (e.getTrafficType()) {
    case SIP_INITIAL:
      ceaseInitialOverload(e.getDetectorType());
      break;

    case SIP_SUBSEQUENT:
      ceaseSubsequentOverload(e.getDetectorType());
      break;

    case HTTP:
      ceaseHttpOverload(e.getDetectorType());
      break;

    case ALL:
      ceaseMaxOverload(e.getDetectorType());
      break;
    }
  }

  public void raiseOverload(OverloadEvent e) {
    switch (e.getTrafficType()) {
    case SIP_INITIAL:
      raiseInitialOverload(e.getDetectorType());
      break;

    case SIP_SUBSEQUENT:
      raiseSubsequentOverload(e.getDetectorType());
      break;

    case HTTP:
      raiseHttpOverload(e.getDetectorType());
      break;

    case ALL:
      raiseMaxOverload(e.getDetectorType());
      break;
    }
  }  
 
}
TOP

Related Classes of com.ericsson.ssa.container.overload.OverloadProtectionManager

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.