HSQLDB backend support completed, but untested.
3 * see AUTHORS for the list of contributors
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 package org.sonews.daemon;
21 import org.sonews.config.Config;
22 import org.sonews.util.Log;
23 import org.sonews.util.Stats;
24 import java.io.IOException;
25 import java.net.InetSocketAddress;
26 import java.net.Socket;
27 import java.nio.channels.SocketChannel;
28 import java.util.ArrayList;
29 import java.util.HashMap;
30 import java.util.List;
31 import java.util.ListIterator;
35 * Daemon thread collecting all NNTPConnection instances. The thread
36 * checks periodically if there are stale/timed out connections and
37 * removes and purges them properly.
38 * @author Christian Lins
41 public final class Connections extends AbstractDaemon
44 private static final Connections instance = new Connections();
47 * @return Active Connections instance.
49 public static Connections getInstance()
51 return Connections.instance;
53 private final List<NNTPConnection> connections = new ArrayList<NNTPConnection>();
54 private final Map<SocketChannel, NNTPConnection> connByChannel = new HashMap<SocketChannel, NNTPConnection>();
58 setName("Connections");
62 * Adds the given NNTPConnection to the Connections management.
64 * @see org.sonews.daemon.NNTPConnection
66 public void add(final NNTPConnection conn)
68 synchronized (this.connections) {
69 this.connections.add(conn);
70 this.connByChannel.put(conn.getSocketChannel(), conn);
76 * @return NNTPConnection instance that is associated with the given
79 public NNTPConnection get(final SocketChannel channel)
81 synchronized (this.connections) {
82 return this.connByChannel.get(channel);
86 int getConnectionCount(String remote)
89 synchronized (this.connections) {
90 for (NNTPConnection conn : this.connections) {
92 assert conn.getSocketChannel() != null;
94 Socket socket = conn.getSocketChannel().socket();
96 InetSocketAddress sockAddr = (InetSocketAddress) socket.getRemoteSocketAddress();
97 if (sockAddr != null) {
98 if (sockAddr.getHostName().equals(remote)) {
102 } // if(socket != null)
109 * Run loops. Checks periodically for timed out connections and purged them
115 while (isRunning()) {
116 int timeoutMillis = 1000 * Config.inst().get(Config.TIMEOUT, 180);
118 synchronized (this.connections) {
119 final ListIterator<NNTPConnection> iter = this.connections.listIterator();
122 while (iter.hasNext()) {
124 if ((System.currentTimeMillis() - conn.getLastActivity()) > timeoutMillis
125 && conn.getBuffers().isOutputBufferEmpty()) {
126 // A connection timeout has occurred so purge the connection
129 // Close and remove the channel
130 SocketChannel channel = conn.getSocketChannel();
131 connByChannel.remove(channel);
134 assert channel != null;
135 assert channel.socket() != null;
137 // Close the channel; implicitely cancels all selectionkeys
139 Log.get().info("Disconnected: " + channel.socket().getRemoteSocketAddress()
141 } catch (IOException ex) {
142 Log.get().warning("Connections.run(): " + ex);
145 // Recycle the used buffers
146 conn.getBuffers().recycleBuffers();
148 Stats.getInstance().clientDisconnect();
154 Thread.sleep(10000); // Sleep ten seconds
155 } catch (InterruptedException ex) {
156 Log.get().warning("Connections Thread was interrupted: " + ex.getMessage());