All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.xsocket.connection.ConnectionManager Maven / Gradle / Ivy

/*
 * Copyright (c) xlightweb.org, 2006 - 2010. All rights reserved.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Please refer to the LGPL license at: http://www.gnu.org/copyleft/lesser.txt
 * The latest copy of this software may be found on http://www.xsocket.org/
 */
package org.xsocket.connection;

import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.xsocket.DataConverter;





/**
 * Connection manager 
 *
 * @author [email protected]
 */
final class ConnectionManager {
	
	private static final Logger LOG = Logger.getLogger(ConnectionManager.class.getName());
	

	// connections
	private final ArrayList> handles = new ArrayList>();
	
	
	
    // watch dog
    private static final long DEFAULT_WATCHDOG_PERIOD_CONNECTION_CHECK_MILLISTION_CHECK_MILLIS =  1L * 60L * 1000L;
    private long watchDogPeriodConCheckMillis = DEFAULT_WATCHDOG_PERIOD_CONNECTION_CHECK_MILLISTION_CHECK_MILLIS;
    private WachdogTask conCheckWatchDogTask = null;
	private int watchDogRuns;


	private int countIdleTimeouts;
	private int countConnectionTimeouts;
	
	private AtomicInteger currentSize = new AtomicInteger(0);
	
	
	public ConnectionManager() {
		updateTimeoutCheckPeriod(watchDogPeriodConCheckMillis);
	}

	
	

	public TimeoutMgmHandle register(NonBlockingConnection connection) {
		TimeoutMgmHandle mgnCon = new TimeoutMgmHandle(connection);
		
		WeakReference ref = mgnCon.getWeakRef();
		if (ref != null) {
		    synchronized (handles) {
		        handles.add(ref);
		    }
		} else {
		    if (LOG.isLoggable(Level.FINE)) {
		        LOG.fine("did not get the weak ref");
		    }
		}
		
		currentSize.incrementAndGet();
		
		if (LOG.isLoggable(Level.FINE)) {
			LOG.fine("connection registered");
		}
		return mgnCon;
	}
	
	long getWatchDogPeriodMillis() {
		return watchDogPeriodConCheckMillis;
	}
	
	int getWatchDogRuns() {
		return watchDogRuns;
	}
	
		
	private void remove(WeakReference handleRef) {
	    synchronized (handles) {
	        handles.remove(handleRef);
        }
		
		currentSize.decrementAndGet();
		
		if (LOG.isLoggable(Level.FINE)) {
		    TimeoutMgmHandle hdl = handleRef.get();
		    if (hdl != null) {
		        INonBlockingConnection con = hdl.getConnection();
		        if (con != null) {
		            LOG.fine("[" + con.getId() + "] handle deregistered (connections size=" + computeSize() + ")");
		        }
		    } 
		}
	}
	
	
	int getSize() {
		return currentSize.get();
	}
	
	
	private int computeSize() {
        synchronized (handles) {
            int size = handles.size();
            currentSize.set(size);
            return size;
        }
	}

	
	@SuppressWarnings("unchecked")
	Set getConnections() {
		final Set cons = new HashSet();
		
		ArrayList> connectionsCopy = null;
		synchronized (handles) {
			 connectionsCopy = (ArrayList>) handles.clone();
		}
		
		for (WeakReference handleRef : connectionsCopy) {
			TimeoutMgmHandle handle = handleRef.get();
			if (handle != null) {
				NonBlockingConnection con = handle.getConnection();
				if (con != null) {
				    cons.add(con);
				}
			}
		}
		
		return cons;
	}
	
	

	
	void close() {
		
		// closing watch dog
		if (conCheckWatchDogTask != null) {
		    conCheckWatchDogTask.cancel();
		    conCheckWatchDogTask = null;
		}

		
		// close open connections
		try {
			for (NonBlockingConnection connection : getConnections()) {
			    try { 
				    connection.close();
			    } catch (IOException ioe) {
	                if (LOG.isLoggable(Level.FINE)) {
	                    LOG.fine("error occured by closing connection " + connection.getId() + " " + DataConverter.toString(ioe));
	                }
	            }
			}
		} catch (Throwable e) {
            if (LOG.isLoggable(Level.FINE)) {
                LOG.fine("error occured by closing open connections " + DataConverter.toString(e));
            }
        }

		
		// clear handle list 
		handles.clear();
	}
	
	

	int getNumberOfIdleTimeouts() {
		return countIdleTimeouts;
	}
	
	int getNumberOfConnectionTimeouts() {
		return countConnectionTimeouts;
	}
    
	void updateTimeoutCheckPeriod(long requiredMinPeriod) {

        // if non watchdog task already exists and the required period is smaller than current one -> return
        if ((conCheckWatchDogTask != null) && (watchDogPeriodConCheckMillis <= requiredMinPeriod)) {
            return;
        }

        // set watch dog period
        watchDogPeriodConCheckMillis = requiredMinPeriod;
        if (LOG.isLoggable(Level.FINE)) {
            LOG.fine("update watchdog period " + DataConverter.toFormatedDuration(watchDogPeriodConCheckMillis));
        }

        
        synchronized (this) {
            
            // if watchdog task task already exits -> terminate it
            if (conCheckWatchDogTask != null) {
                TimerTask tt = conCheckWatchDogTask;
                conCheckWatchDogTask = null;
                tt.cancel();
            }


            
            // create and run new watchdog task
            conCheckWatchDogTask = new WachdogTask();
            IoProvider.getTimer().schedule(conCheckWatchDogTask, watchDogPeriodConCheckMillis, watchDogPeriodConCheckMillis);
            
        }
	}	
	
	
	private final class WachdogTask extends TimerTask {
        
        @Override
        public void run() {
            try {
                check();
            } catch (Exception e) {
                
                // eat and log exception 
                if (LOG.isLoggable(Level.FINE)) {
                    LOG.fine("error occured by running check: " + e.toString());
                }
            }
        }
	}
	

	
	
	@SuppressWarnings("unchecked")
	void check() {
		
		watchDogRuns++;
		
		long current = System.currentTimeMillis();
            
		ArrayList> connectionsCopy = null;
		synchronized (handles) {
		    connectionsCopy = (ArrayList>) handles.clone();
		}
    		
		for (WeakReference handleRef : connectionsCopy) {
            	
		    TimeoutMgmHandle handle = handleRef.get();
		    if (handle == null) {
		        remove(handleRef);
            		
		    } else {
		        NonBlockingConnection con = handle.getConnection();
		        if (con.isOpen()) {
		            checkTimeout(con, current);	
	            		
		        } else {
		            remove(handleRef);
		        }
		    }
		}
		
		computeSize();
    }
    
	


	private void checkTimeout(NonBlockingConnection connection, long current) {


       boolean timeoutOccured = connection.checkIdleTimeout(current);
       if (timeoutOccured) {
           countIdleTimeouts++;
       }

       timeoutOccured = connection.checkConnectionTimeout(current);
       if (timeoutOccured) {
           countConnectionTimeouts++;
       }
	}
   

	
	
	final class TimeoutMgmHandle {
		
		private final NonBlockingConnection con;
		private WeakReference handleRef;
		
		public TimeoutMgmHandle(NonBlockingConnection connection) {
			con = connection;
			handleRef = new WeakReference(this);
		}
		
		WeakReference getWeakRef() {
		    return handleRef;
		}
		
		
		void updateCheckPeriod(long period) {
			updateTimeoutCheckPeriod(period);
		}
		
		void destroy() {
		    if (handleRef != null) {
		        remove(handleRef);
		        handleRef = null;
		    }
		}
	
		NonBlockingConnection getConnection() {
			return con;
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy