/* * JLibs: Common Utilities for Java * Copyright (C) 2009 Santhosh Kumar T <santhosh.tekuri@gmail.com> * * 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. */ package jlibs.nio; import java.util.HashMap; import java.util.Map; import static jlibs.nio.Debugger.DEBUG; import static jlibs.nio.Debugger.println; /** * @author Santhosh Kumar Tekuri */ public class ConnectionPool{ private final Reactor reactor; public long timeout = 60*1000; Map<String, Entry> entries = new HashMap<>(); private int count; ConnectionPool(Reactor reactor){ this.reactor = reactor; } public int count(){ return count; } public void add(String key, Connection connection){ add(key, connection, timeout); } public void add(String key, Connection connection, long timeout){ // todo: transport is null for PipedConnection if(connection.transport.peekInInterested || connection.transport.peekOutInterested) throw new IllegalArgumentException("connection.interestOps!=0"); if(timeout<=0){ timeout = this.timeout; if(timeout<=0) timeout = 60*1000; } Entry entry = entries.get(key); if(entry==null) entries.put(key, entry=new Entry(key)); entry.add(connection, timeout); } public Connection remove(String key){ Entry entry = entries.get(key); return entry==null ? null : entry.remove(); } public void remove(Connection connection){ if(connection.poolPrev!=null && connection.poolNext!=null) entries.get(connection.poolKey).remove(connection); } public class Entry{ public final String key; int count; public Entry(String key){ this.key = key; } private Connection head; public void add(Connection con, long timeout){ if(con.poolPrev==null && con.poolNext==null){ if(DEBUG) println("connectionPool.add("+con+", "+timeout+")"); con.poolKey = key; // con.addingToPool(); if(head==null){ con.poolPrev = con; con.poolNext = con; }else{ Connection tail = head.poolPrev; con.poolNext = head; head.poolPrev = con; con.poolPrev = tail; tail.poolNext = con; } head = con; reactor.startTimer(con, timeout); ++count; ++ConnectionPool.this.count; con.workingFor = con; con.executionID = null; } } public Connection remove(){ if(head==null) return null; Connection connection = head; remove(head); return connection; } void remove(Connection con){ if(DEBUG) println("connectionPool.remove("+con+")"); if(con.heapIndex!=-1) reactor.stopTimer(con); // con.initWorkingFor(); if(con==head){ if(head.poolNext==head && head.poolPrev==head){ head = null; }else{ Connection tail = head.poolPrev; head = head.poolNext; head.poolPrev = tail; tail.poolNext = head; } }else{ Connection before = con.poolPrev; Connection after = con.poolNext; before.poolNext = after; after.poolPrev = before; } con.poolPrev = null; con.poolNext = null; --count; --ConnectionPool.this.count; con.taskCompleted(); con.workingFor = reactor.getExecutionOwner(); if(con.workingFor==null) con.workingFor = con; con.makeActive(); } } }