chris@1: /*
chris@1: * SONEWS News Server
chris@1: * see AUTHORS for the list of contributors
chris@1: *
chris@1: * This program is free software: you can redistribute it and/or modify
chris@1: * it under the terms of the GNU General Public License as published by
chris@1: * the Free Software Foundation, either version 3 of the License, or
chris@1: * (at your option) any later version.
chris@1: *
chris@1: * This program is distributed in the hope that it will be useful,
chris@1: * but WITHOUT ANY WARRANTY; without even the implied warranty of
chris@1: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
chris@1: * GNU General Public License for more details.
chris@1: *
chris@1: * You should have received a copy of the GNU General Public License
chris@1: * along with this program. If not, see .
chris@1: */
chris@1:
chris@1: package org.sonews.daemon;
chris@1:
chris@1: import org.sonews.util.Log;
chris@1: import java.nio.ByteBuffer;
chris@1: import java.nio.channels.SocketChannel;
chris@1: import java.util.concurrent.ArrayBlockingQueue;
chris@1:
chris@1: /**
chris@1: * Does most of the work: parsing input, talking to client and Database.
chris@1: * @author Christian Lins
chris@1: * @since sonews/0.5.0
chris@1: */
chris@1: class ConnectionWorker extends AbstractDaemon
chris@1: {
chris@1:
chris@1: // 256 pending events should be enough
chris@1: private static ArrayBlockingQueue pendingChannels
chris@1: = new ArrayBlockingQueue(256, true);
chris@1:
chris@1: /**
chris@1: * Registers the given channel for further event processing.
chris@1: * @param channel
chris@1: */
chris@1: public static void addChannel(SocketChannel channel)
chris@1: throws InterruptedException
chris@1: {
chris@1: pendingChannels.put(channel);
chris@1: }
chris@1:
chris@1: /**
chris@1: * Processing loop.
chris@1: */
chris@1: @Override
chris@1: public void run()
chris@1: {
chris@1: while(isRunning())
chris@1: {
chris@1: try
chris@1: {
chris@1: // Retrieve and remove if available, otherwise wait.
chris@1: SocketChannel channel = pendingChannels.take();
chris@1:
chris@1: if(channel != null)
chris@1: {
chris@1: // Connections.getInstance().get() MAY return null
chris@1: NNTPConnection conn = Connections.getInstance().get(channel);
chris@1:
chris@1: // Try to lock the connection object
chris@1: if(conn != null && conn.tryReadLock())
chris@1: {
chris@1: ByteBuffer buf = conn.getBuffers().nextInputLine();
chris@1: while(buf != null) // Complete line was received
chris@1: {
chris@1: final byte[] line = new byte[buf.limit()];
chris@1: buf.get(line);
chris@1: ChannelLineBuffers.recycleBuffer(buf);
chris@1:
chris@1: // Here is the actual work done
chris@1: conn.lineReceived(line);
chris@1:
chris@1: // Read next line as we could have already received the next line
chris@1: buf = conn.getBuffers().nextInputLine();
chris@1: }
chris@1: conn.unlockReadLock();
chris@1: }
chris@1: else
chris@1: {
chris@1: addChannel(channel);
chris@1: }
chris@1: }
chris@1: }
chris@1: catch(InterruptedException ex)
chris@1: {
chris@1: Log.msg("ConnectionWorker interrupted: " + ex, true);
chris@1: }
chris@1: catch(Exception ex)
chris@1: {
chris@1: Log.msg("Exception in ConnectionWorker: " + ex, false);
chris@1: ex.printStackTrace();
chris@1: }
chris@1: } // end while(isRunning())
chris@1: }
chris@1:
chris@1: }