/* This file is part of VoltDB. * Copyright (C) 2008-2010 VoltDB Inc. * * VoltDB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * VoltDB 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with VoltDB. If not, see <http://www.gnu.org/licenses/>. */ package org.voltdb.network; import java.util.concurrent.atomic.AtomicLong; import java.nio.ByteBuffer; import java.io.IOException; public abstract class VoltProtocolHandler implements InputHandler { /** VoltProtocolPorts each have a unique id */ private static AtomicLong m_globalConnectionCounter = new AtomicLong(0); /** messages read by this connection */ private int m_sequenceId; /** serial number of this VoltPort */ private final long m_connectionId; private int m_nextLength; public VoltProtocolHandler() { m_sequenceId = 0; m_connectionId = m_globalConnectionCounter.incrementAndGet(); } @Override public ByteBuffer retrieveNextMessage(Connection c) throws IOException { final NIOReadStream inputStream = c.readStream(); /* * Note that access to the read stream is not synchronized. In this application * the VoltPort will invoke this input handler to interact with the read stream guaranteeing * thread safety. That said the Connection interface does allow other parts of the application * access to the read stream. */ ByteBuffer result = null; if (m_nextLength == 0 && inputStream.dataAvailable() > (Integer.SIZE/8)) { m_nextLength = inputStream.getInt(); if (m_nextLength < 1) { throw new IOException( "Next message length is " + m_nextLength + " which is less than 1 and is nonsense"); } if (m_nextLength > 52428800) { throw new IOException( "Next message length is " + m_nextLength + " which is greater then the hard coded " + "max of 52428800. Break up the work into smaller chunks (2 megabytes is reasonable) " + "and send as multiple messages or stored procedure invocations"); } assert m_nextLength > 0; } if (m_nextLength > 0 && inputStream.dataAvailable() >= m_nextLength) { result = ByteBuffer.allocate(m_nextLength); inputStream.getBytes(result.array()); m_nextLength = 0; m_sequenceId++; } return result; } @Override public void started(Connection c) { } @Override public void starting(Connection c) { } @Override public void stopped(Connection c) { } @Override public void stopping(Connection c) { } @Override public long connectionId() { return m_connectionId; } public int sequenceId() { return m_sequenceId; } protected int getNextMessageLength() { return m_nextLength; } }