blob: fb2097cb9c9f0a3e47e3234968037157020f1285 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.yoko.orb.OB;
import java.util.concurrent.ExecutorService;
import java.util.logging.Level;
final class GIOPServerStarterThreaded extends GIOPServerStarter {
//
// The starter thread
//
protected final class Starter implements Runnable {
public void run() {
try {
starterRun();
} catch (RuntimeException ex) {
Assert._OB_assert(ex);
}
logger.fine("Shutting down ORB server listener thread");
//
// Shutdown the acceptor so that no further connections are
// accepted
//
logCloseAcceptor();
acceptor_.shutdown();
//
// Accept all connections which might have queued up in the
// listen() backlog
while (true) {
org.apache.yoko.orb.OCI.Transport transport = null;
try {
transport = acceptor_.accept(false);
} catch (org.omg.CORBA.SystemException ex) {
}
if (transport == null) {
logger.fine("Null transport received from a connect");
break;
}
try {
GIOPConnection connection = new GIOPConnectionThreaded(
orbInstance_, transport,
oaInterface_);
connection.setState(GIOPConnection.State.Closing);
} catch (org.omg.CORBA.SystemException ex) {
// Ignore SystemExceptions
}
}
//
// Close the acceptor
//
acceptor_.close();
}
}
// ----------------------------------------------------------------------
// GIOPServerStarterThreaded package member implementation
// ----------------------------------------------------------------------
GIOPServerStarterThreaded(ORBInstance orbInstance,
org.apache.yoko.orb.OCI.Acceptor acceptor, OAInterface oaInterface) {
super(orbInstance, acceptor, oaInterface);
logger.fine("GIOPServer thread started " + this + " using acceptor " + acceptor);
try {
//
// Retrieve the thread group for the servers
//
ExecutorService executor = orbInstance_.getServerExecutor();
//
// Start starter thread
//
executor.submit(new Starter());
} catch (OutOfMemoryError ex) {
acceptor_.close();
state_ = StateClosed;
throw new org.omg.CORBA.IMP_LIMIT(org.apache.yoko.orb.OB.MinorCodes
.describeImpLimit(org.apache.yoko.orb.OB.MinorCodes.MinorThreadLimit),
org.apache.yoko.orb.OB.MinorCodes.MinorThreadLimit,
org.omg.CORBA.CompletionStatus.COMPLETED_NO);
}
}
// ----------------------------------------------------------------------
// GIOPServerStarterThreaded public member implementation
// ----------------------------------------------------------------------
//
// Change the state of the worker
//
synchronized public void setState(int state) {
//
// Don't do anything if there is no state change
//
if (state_ == state) {
return;
}
logger.fine("Setting server state to " + state);
//
// It is not possible to transition backwards, except if we are
// in holding state
//
if (state_ != StateHolding && state < state_) {
return;
}
switch (state) {
case StateActive: {
for (int i = 0; i < connections_.size(); i++) {
GIOPConnection w = (GIOPConnection) connections_.elementAt(i);
w.setState(GIOPConnection.State.Active);
}
break;
}
case StateHolding:
for (int i = 0; i < connections_.size(); i++) {
GIOPConnection w = (GIOPConnection) connections_.elementAt(i);
w.setState(GIOPConnection.State.Holding);
}
break;
case StateClosed: {
for (int i = 0; i < connections_.size(); i++) {
GIOPConnection w = (GIOPConnection) connections_.elementAt(i);
w.setState(GIOPConnection.State.Closing);
}
connections_.removeAllElements();
//
// Connect to this starter's acceptor, to unblock the call
// to accept() in the starter thread
//
try {
org.apache.yoko.orb.OCI.Transport tr = acceptor_.connect_self();
tr.close();
} catch (org.omg.CORBA.SystemException ex) {
//
// Ignore all system exceptions
//
}
break;
}
}
//
// Update the state and notify about the state change
//
state_ = state;
notifyAll();
}
//
// Run method for starter thread
//
public void starterRun() {
while (true) {
//
// Get new transport, blocking
//
org.apache.yoko.orb.OCI.Transport transport = null;
try {
transport = acceptor_.accept(true);
Assert._OB_assert(transport != null);
} catch (org.omg.CORBA.NO_PERMISSION ex) {
//
// Ignore NO_PERMISSION exceptions
//
} catch (org.omg.CORBA.SystemException ex) {
//
// Ignore exception. This probably means that the server
// exceeded the number of available file descriptors.
//
}
synchronized (this) {
//
// Reap the existing set of workers
//
reapWorkers();
//
// Check whether we are on hold
//
while (state_ == StateHolding) {
try {
logger.fine("Waiting on an inbound connection because the state is holding. acceptor=" + acceptor_);
wait();
} catch (InterruptedException ex) {
}
}
logger.fine("Processing an inbound connection with state=" + state_);
if (transport != null) {
try {
if (state_ == StateActive) {
//
// If we're active, we create and add a new
// worker to the worker list
//
GIOPConnection connection = new GIOPConnectionThreaded(
orbInstance_, transport, oaInterface_);
connections_.addElement(connection);
connection.setState(GIOPConnection.State.Active);
} else {
logger.fine("Processing an inbound connection because state is closed");
//
// If we're closed, we create a new dummy
// worker, only in order to set it to
// StateClosing for proper connection shutdown
//
Assert._OB_assert(state_ == StateClosed);
logger.fine("Processing an inbound connection because state is closed");
GIOPConnection connection = new GIOPConnectionThreaded(
orbInstance_, transport, oaInterface_);
logger.fine("Created connection " + connection);
connection.setState(GIOPConnection.State.Closing);
logger.fine("set connection state to closing");
}
} catch (org.omg.CORBA.SystemException ex) {
String msg = "can't accept connection\n" + ex.getMessage();
logger.log(java.util.logging.Level.WARNING, msg, ex);
}
}
if (state_ == StateClosed) {
logger.fine("Shutting down server thread");
break;
}
}
}
}
}