/* * JacORB - a free Java ORB * * Copyright (C) 1997-2014 Gerald Brose / The JacORB Team. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ package org.jacorb.orb.giop; import org.jacorb.config.Configuration; import org.jacorb.config.ConfigurationException; import org.jacorb.orb.iiop.IIOPConnection; /** * @author Nicolas Noffke */ public class ServerGIOPConnection extends GIOPConnection { private static final byte[] CLOSE_CONNECTION_MESSAGE = new byte[] { // Byte casts are for JDK1.2 compatibility. (byte )'G', (byte )'I', (byte )'O', (byte )'P', //magic start 1, //GIOP major 0, //GIOP minor 0, //endianess, big-endian 5, //message type, CloseConnection message 0, 0, 0, 0 // message size, 0 because CloseConnection has no body }; private final GIOPConnectionManager manager; private boolean closeOnReadTimeout = false; private boolean delayClose = false; public ServerGIOPConnection( org.omg.ETF.Profile profile, org.omg.ETF.Connection transport, RequestListener request_listener, ReplyListener reply_listener, StatisticsProvider statistics_provider, GIOPConnectionManager manager ) { super( profile, transport, request_listener, reply_listener, statistics_provider ); this.manager = manager; } public void configure(Configuration configuration) throws ConfigurationException { super.configure(configuration); delayClose = configuration.getAttributeAsBoolean("jacorb.connection.delay_close", false); int max_reply_write_time = configuration.getAttributeAsInteger("jacorb.connection.reply.write_timeout", 0); init_write_monitor (max_reply_write_time); } /** * Try an orderly shutdown of this connection by sending a * CloseConnection message. The CORBA spec only allows us to * do that if we have no more pending messages for which we * haven't sent a reply yet (CORBA 3.0, 15.5.1.1). If there are * pending messages, this method does nothing and returns false. * If there are no pending messages, it sets the connection into * discarding mode, sends the CloseConnection message, and reports * the connection as closed to any connection_listener that's registered * with this connection. The actual closing of the connection will happen * later, when the transport gets closed by the client, or the final * timeout has passed. */ boolean tryClose() { if( tryDiscard() ) { if (logger.isDebugEnabled()) { logger.debug(this.toString() + ": tryClose() -- will send close connection"); } sendCloseConnection(); closeOnReadTimeout = true; if( connection_listener != null ) { connection_listener.connectionClosed(); } return true; } if (logger.isDebugEnabled()) { logger.debug(this.toString() + ": tryClose() -- cannot close connection"); } return false; } /** * Atomically try to set this connection into discarding mode, if * it doesn't have any pending messages. * * @return true, if the connection has been idle and discarding * has been set */ private boolean tryDiscard() { if( ! hasPendingMessages() ) { synchronized( pendingUndecidedSync ) { discard_messages = true; } return true; } return false; } /** * Sends a close connection message flushing the transport. */ private void sendCloseConnection() { try { getWriteLock(0); write( CLOSE_CONNECTION_MESSAGE, 0, CLOSE_CONNECTION_MESSAGE.length ); transport.flush(); if (getStatisticsProviderAdapter() != null) { getStatisticsProviderAdapter().flushed(); } if( delayClose && transport instanceof IIOPConnection ) { ((IIOPConnection)transport).turnOnFinalTimeout(); } else { // Set do_close to true so anything waiting in waitUntilConnection // doesn't think there is a possibility of connecting. I think. do_close = true; transport.close(); } } catch( org.omg.CORBA.COMM_FAILURE e ) { logger.error ( "COMM_FAILURE in sendCloseConnection(), in " + this.toString(), e ); } finally { releaseWriteLock(); } if( manager != null ) { manager.unregisterServerGIOPConnection( this ); } } /** * Server-side implementation what to do when a read timeout occurs. * We react by trying an orderly shutdown that's initiated with * a CloseConnection message. If this timeout occured after we have * already sent CloseConnection, just close down unconditionally. */ protected void readTimedOut() { if (logger.isDebugEnabled()) { logger.debug (this.toString() + ": readTimedOut()"); } if( closeOnReadTimeout ) { // we get here if we have sent a CloseConnection message // on this connection before close(); } else { // attempt an orderly shutdown by sending a CloseConnection // message tryClose(); } } /** * Server-side implementation what to do if the underlying transport * gets closed during a read operation. Since we're server-side and * can't reopen, we simply close completely. */ protected void streamClosed() { if (logger.isDebugEnabled()) { logger.debug (this.toString() + ": streamClosed()"); } close(); } /** * @see GIOPConnection#close() */ public void close() { super.close(); if( manager != null ) { manager.unregisterServerGIOPConnection( this ); } } public String toString() { if (profile != null) { return "ServerGIOPConnection to " + profile.toString() + " from " + orb.getBasicAdapter ().getEndpointProfiles () + " (" + Integer.toHexString(this.hashCode()) + ")"; } return super.toString(); } }// ServerGIOPConnection