Main Page | Packages | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages

ConnectionClosingThread.java

00001 /**
00002  * C-JDBC: Clustered JDBC.
00003  * Copyright (C) 2002-2004 French National Institute For Research In Computer
00004  * Science And Control (INRIA).
00005  * Contact: c-jdbc@objectweb.org
00006  * 
00007  * This library is free software; you can redistribute it and/or modify it
00008  * under the terms of the GNU Lesser General Public License as published by the
00009  * Free Software Foundation; either version 2.1 of the License, or any later
00010  * version.
00011  * 
00012  * This library is distributed in the hope that it will be useful, but WITHOUT
00013  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
00015  * for more details.
00016  * 
00017  * You should have received a copy of the GNU Lesser General Public License
00018  * along with this library; if not, write to the Free Software Foundation,
00019  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00020  *
00021  * Initial developer(s): Emmanuel Cecchet.
00022  * Contributor(s): ______________________________________.
00023  */
00024 
00025 package org.objectweb.cjdbc.driver;
00026 
00027 import java.util.ArrayList;
00028 
00029 import org.objectweb.cjdbc.driver.protocol.Commands;
00030 
00031 /**
00032  * The <code>ConnectionClosingThread</code> wakes up every 5 seconds when
00033  * close() has been called on a connection and it frees the connection if it has
00034  * not been reused.
00035  * 
00036  * @author <a href="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
00037  * @version 1.0
00038  */
00039 public class ConnectionClosingThread extends Thread
00040 {
00041   /* wait time before closing a connection in ms */
00042   private static final int WAIT_TIME = 5000;
00043 
00044   private Driver           driver;
00045   private ArrayList        pendingConnectionClosing;
00046 
00047   /**
00048    * Builds a new ConnectionClosingThread
00049    * 
00050    * @param driver The driver that created us
00051    */
00052   public ConnectionClosingThread(Driver driver)
00053   {
00054     super("ConnectionClosingThread");
00055     this.driver = driver;
00056     this.pendingConnectionClosing = driver.pendingConnectionClosing;
00057     driver.connectionClosingThreadisAlive = true;
00058   }
00059 
00060   /**
00061    * The connection closing thread wakes up every WAIT_TIME seconds when close()
00062    * has been called on a connection and it frees the connection if it has not
00063    * been reused.
00064    */
00065   public void run()
00066   {
00067     try
00068     {
00069       Connection firstConnectionToClose = null;
00070       Connection lastConnectionToClose = null;
00071       int pendingConnectionSize;
00072       ArrayList closingList = new ArrayList();
00073       boolean killed = false;
00074 
00075       while (!killed)
00076       {
00077         synchronized (pendingConnectionClosing)
00078         {
00079           pendingConnectionSize = pendingConnectionClosing.size();
00080           if (pendingConnectionSize == 0)
00081             break;
00082 
00083           try
00084           {
00085             // Look at the connections in the queue before sleeping
00086             firstConnectionToClose = (Connection) pendingConnectionClosing
00087                 .get(0);
00088             lastConnectionToClose = (Connection) pendingConnectionClosing
00089                 .get(pendingConnectionSize - 1);
00090 
00091             // Sleep
00092             pendingConnectionClosing.wait(WAIT_TIME);
00093           }
00094           catch (InterruptedException ignore)
00095           {
00096           }
00097 
00098           pendingConnectionSize = pendingConnectionClosing.size();
00099           // Exit, no more connections
00100           if (pendingConnectionSize == 0)
00101             break;
00102 
00103           // Compare the queue now with its state when we got to sleep
00104           if (firstConnectionToClose == pendingConnectionClosing.get(0))
00105           { // Ok, the connection has not been reused, let's close it
00106             if (lastConnectionToClose == (Connection) pendingConnectionClosing
00107                 .get(pendingConnectionSize - 1))
00108             { // No connection has been reused, remove them all
00109               closingList.addAll(pendingConnectionClosing);
00110               pendingConnectionClosing.clear();
00111               killed = true; // Let's die, there are no more connections
00112             }
00113             else
00114               // Close only the first connection
00115               closingList.add(pendingConnectionClosing.remove(0));
00116           }
00117         }
00118 
00119         // Effectively close the connections outside the synchronized block
00120         while (!closingList.isEmpty())
00121           closeConnection((Connection) closingList.remove(0));
00122       }
00123     }
00124     catch (RuntimeException e)
00125     {
00126       e.printStackTrace();
00127     }
00128     finally
00129     {
00130       synchronized (pendingConnectionClosing)
00131       {
00132         driver.connectionClosingThreadisAlive = false;
00133       }
00134     }
00135   }
00136 
00137   /**
00138    * Closes a connection.
00139    * 
00140    * @param c the connection to close
00141    */
00142   private void closeConnection(Connection c)
00143   {
00144     try
00145     {
00146       // Unlink those objects so that this connection can be garbage collected
00147       c.driver = null;
00148       if (c.socketOutput != null)
00149       {
00150         c.socketOutput.writeInt(Commands.Close);
00151         c.socketOutput.flush();
00152         if (c.socketInput != null)
00153         { // Wait for the controller to receive the connection and close the
00154           // stream. If we do not wait for the controller ack, the connection is
00155           // closed on the controller before the closing is handled which
00156           // results in an ugly warning message on the controller side. We are
00157           // not in a hurry when closing the connection so let do the things
00158           // nicely!
00159           c.socketInput.readObject();
00160           c.socketInput.close();
00161         }
00162         c.socketOutput.close();
00163       }
00164 
00165       if (c.socket != null)
00166         c.socket.close();
00167     }
00168     catch (Exception ignore)
00169     {
00170     }
00171   }
00172 
00173 }

Generated on Mon Apr 11 22:01:30 2005 for C-JDBC by  doxygen 1.3.9.1