Package com.caucho.server.resin

Source Code of com.caucho.server.resin.ResinWaitForExitService

/*
* Copyright (c) 1998-2011 Caucho Technology -- all rights reserved
*
* This file is part of Resin(R) Open Source
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Resin Open Source is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Resin Open Source is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
* of NON-INFRINGEMENT.  See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Resin Open Source; if not, write to the
*
*   Free Software Foundation, Inc.
*   59 Temple Place, Suite 330
*   Boston, MA 02111-1307  USA
*
* @author Scott Ferguson
*/

package com.caucho.server.resin;

import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.caucho.env.service.ResinSystem;
import com.caucho.env.shutdown.ExitCode;
import com.caucho.env.shutdown.ShutdownSystem;
import com.caucho.env.thread.ThreadPool;
import com.caucho.env.warning.WarningService;
import com.caucho.util.L10N;
import com.caucho.vfs.ReadStream;

/**
* The wait-for-exit service waits for Resin to exit.
*/
class ResinWaitForExitService
{
  private static final Logger log
    = Logger.getLogger(ResinWaitForExitService.class.getSimpleName());
 
  private static final L10N L = new L10N(ResinWaitForExitService.class);
 
  private Resin _resin;
  private ResinSystem _resinSystem;
  private InputStream _waitIn;
  private Socket _pingSocket;
  private ResinActor _resinActor;

  /**
   * Creates a new resin server.
   */
  ResinWaitForExitService(Resin resin,
                          ResinSystem resinSystem,
                          InputStream waitIn,
                          Socket pingSocket)
  {
    _resin = resin;
    _resinSystem = resinSystem;
    _waitIn = waitIn;
    _pingSocket = pingSocket;
  }
 
  ResinActor getResinActor()
  {
    return _resinActor;
  }

  /**
   * Thread to wait until Resin should be stopped.
   */
  void waitForExit()
  {
    int socketExceptionCount = 0;
    Runtime runtime = Runtime.getRuntime();
   
    ShutdownSystem shutdown = _resinSystem.getService(ShutdownSystem.class);
   
    if (shutdown == null) {
      throw new IllegalStateException(L.l("'{0}' requires an active {1}",
                                          this,
                                          ShutdownSystem.class.getSimpleName()));
    }
   
    /*
     * If the server has a parent process watching over us, close
     * gracefully when the parent dies.
     */
    while (! _resin.isClosing()) {
      try {
        Thread.sleep(10);
       
        if (! checkMemory(runtime)) {
          shutdown.shutdown(ExitCode.MEMORY, "Resin shutdown from out of memory");
          // dumpHeapOnExit();
          return;
        }
       
        if (! checkFileDescriptor()) {
          shutdown.shutdown(ExitCode.MEMORY,
                            "Resin shutdown from out of file descriptors");
          //dumpHeapOnExit();
          return;
        }
       
        if (_waitIn != null) {
          if (_waitIn.read() >= 0) {
            socketExceptionCount = 0;
          }
          else {
            shutdown.shutdown(ExitCode.WATCHDOG_EXIT,
                              "Stopping due to watchdog or user.");
           
            return;
          }
        }
        else {
          synchronized (this) {
            wait(10000);
          }
        }
      } catch (SocketTimeoutException e) {
        socketExceptionCount = 0;
      } catch (InterruptedIOException e) {
        socketExceptionCount = 0;
      } catch (InterruptedException e) {
        socketExceptionCount = 0;
      } catch (SocketException e) {
        // The Solaris JVM will throw SocketException periodically
        // instead of interrupted exception, so those exceptions need to
        // be ignored.
       
        // However, the Windows JVMs will throw connection reset by peer
        // instead of returning an end of file in the read. So those
        // need to be trapped to close the socket.
        if (socketExceptionCount++ == 0) {
          log.log(Level.FINE, e.toString(), e);
        }
        else if (socketExceptionCount > 100)
          return;
      } catch (OutOfMemoryError e) {
        String msg = "Resin shutdown from out of memory";
       
        ShutdownSystem.shutdownOutOfMemory(msg);
      } catch (Throwable e) {
        log.log(Level.WARNING, e.toString(), e);
       
        return;
      }
    }
  }

  private boolean checkMemory(Runtime runtime)
    throws InterruptedException
  {
    long minFreeMemory = 0;//_resinConfig.getMinFreeMemory();

    if (minFreeMemory <= 0) {
      // memory check disabled
      return true;
    }
    else if (2 * minFreeMemory < getFreeMemory(runtime)) {
      // plenty of free memory
      return true;
    }
    else {
      if (log.isLoggable(Level.FINER)) {
        log.finer(L.l("free memory {0} max:{1} total:{2} free:{3}",
                          "" + getFreeMemory(runtime),
                          "" + runtime.maxMemory(),
                          "" + runtime.totalMemory(),
                          "" + runtime.freeMemory()));
      }

      log.info(L.l("Forcing GC due to low memory. {0} free bytes.",
                       getFreeMemory(runtime)));

      runtime.gc();

      Thread.sleep(1000);

      runtime.gc();

      if (getFreeMemory(runtime) < minFreeMemory) {
        log.severe(L.l("Restarting due to low free memory. {0} free bytes",
                           getFreeMemory(runtime)));

        return false;
      }
    }

    // second memory check
    allocateMemory();

    return true;
  }
 
  private Object allocateMemory()
  {
    return new Object();
  }

  private boolean checkFileDescriptor()
  {
    try {
      ReadStream is = _resin.getResinConf().openRead();
      is.close();

      return true;
    } catch (IOException e) {
      log.severe(L.l("Restarting due to file descriptor failure:\n{0}",
                     e));

      return false;
    }
  }

  private static long getFreeMemory(Runtime runtime)
  {
    long maxMemory = runtime.maxMemory();
    long totalMemory = runtime.totalMemory();
    long freeMemory = runtime.freeMemory();

    // Some JDKs (JRocket) return 0 for the maxMemory
    if (maxMemory < totalMemory)
      return freeMemory;
    else
      return maxMemory - totalMemory + freeMemory;
  }

  void startResinActor()
    throws IOException
  {
    Thread thread = Thread.currentThread();
    ClassLoader loader = thread.getContextClassLoader();
   
    try {
      thread.setContextClassLoader(_resinSystem.getClassLoader());
     
      WarningService warning = WarningService.getCurrent();

      if (_pingSocket != null) {
        _resinActor = new ResinActor(_resin);
        warning.addHandler(new ResinWarningHandler(_resinActor));

        InputStream is = _pingSocket.getInputStream();
        OutputStream os = _pingSocket.getOutputStream();

        ResinLink link = new ResinLink(_resinActor, is, os);

        ThreadPool.getThreadPool().schedule(link);
      }
    } finally {
      thread.setContextClassLoader(loader);
    }
  }

  @Override
  public String toString()
  {
    return getClass().getSimpleName() + "[id=" + _resinSystem.getId() + "]";
  }

}
TOP

Related Classes of com.caucho.server.resin.ResinWaitForExitService

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.