/**
* Copyright (c) 2002-2012 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.com;
import java.io.IOException;
import java.nio.ByteBuffer;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.handler.codec.frame.LengthFieldBasedFrameDecoder;
import org.jboss.netty.handler.codec.frame.LengthFieldPrepender;
public abstract class Protocol
{
public static final int PORT = 8901;
public static final int MEGA = 1024 * 1024;
public static final int DEFAULT_FRAME_LENGTH = 16*MEGA;
public static final ObjectSerializer<Integer> INTEGER_SERIALIZER = new ObjectSerializer<Integer>()
{
@SuppressWarnings( "boxing" )
public void write( Integer responseObject, ChannelBuffer result ) throws IOException
{
result.writeInt( responseObject );
}
};
public static final ObjectSerializer<Long> LONG_SERIALIZER = new ObjectSerializer<Long>()
{
@SuppressWarnings( "boxing" )
public void write( Long responseObject, ChannelBuffer result ) throws IOException
{
result.writeLong( responseObject );
}
};
public static final ObjectSerializer<Void> VOID_SERIALIZER = new ObjectSerializer<Void>()
{
public void write( Void responseObject, ChannelBuffer result ) throws IOException
{
}
};
public static final Deserializer<Integer> INTEGER_DESERIALIZER = new Deserializer<Integer>()
{
public Integer read( ChannelBuffer buffer, ByteBuffer temporaryBuffer ) throws IOException
{
return buffer.readInt();
}
};
public static final Deserializer<Void> VOID_DESERIALIZER = new Deserializer<Void>()
{
public Void read( ChannelBuffer buffer, ByteBuffer temporaryBuffer ) throws IOException
{
return null;
}
};
public static final Serializer EMPTY_SERIALIZER = new Serializer()
{
public void write( ChannelBuffer buffer, ByteBuffer readBuffer ) throws IOException
{
}
};
public static class FileStreamsDeserializer implements Deserializer<Void>
{
private final StoreWriter writer;
public FileStreamsDeserializer( StoreWriter writer )
{
this.writer = writer;
}
// NOTICE: this assumes a "smart" ChannelBuffer that continues to next chunk
public Void read( ChannelBuffer buffer, ByteBuffer temporaryBuffer ) throws IOException
{
int pathLength;
while ( 0 != ( pathLength = buffer.readUnsignedShort() ) )
{
String path = readString( buffer, pathLength );
boolean hasData = buffer.readByte() == 1;
writer.write( path, hasData ? new BlockLogReader( buffer ) : null, temporaryBuffer, hasData );
}
writer.done();
return null;
}
};
public static void addLengthFieldPipes( ChannelPipeline pipeline, int frameLength )
{
pipeline.addLast( "frameDecoder",
new LengthFieldBasedFrameDecoder( frameLength+4, 0, 4, 0, 4 ) );
pipeline.addLast( "frameEncoder", new LengthFieldPrepender( 4 ) );
}
public static void writeString( ChannelBuffer buffer, String name )
{
char[] chars = name.toCharArray();
buffer.writeInt( chars.length );
writeChars( buffer, chars );
}
public static void writeChars( ChannelBuffer buffer, char[] chars )
{
// TODO optimize?
for ( char ch : chars )
{
buffer.writeChar( ch );
}
}
public static String readString( ChannelBuffer buffer )
{
return readString( buffer, buffer.readInt() );
}
public static boolean readBoolean( ChannelBuffer buffer )
{
byte value = buffer.readByte();
switch ( value )
{
case 0: return false;
case 1: return true;
default: throw new ComException( "Invalid boolean value " + value );
}
}
public static String readString( ChannelBuffer buffer, int length )
{
char[] chars = new char[length];
for ( int i = 0; i < length; i++ )
{
chars[i] = buffer.readChar();
}
return new String( chars );
}
public static void assertChunkSizeIsWithinFrameSize( int chunkSize, int frameLength )
{
if ( chunkSize > frameLength )
throw new IllegalArgumentException( "Chunk size " + chunkSize +
" needs to be equal or less than frame length " + frameLength );
}
}