Author: j16sdiz Date: 2008-05-09 14:28:23 +0000 (Fri, 09 May 2008) New Revision: 19875
Added: trunk/freenet/src/freenet/support/ByteBufferInputStream.java Modified: trunk/freenet/src/freenet/io/comm/FreenetInetAddress.java trunk/freenet/src/freenet/io/comm/Message.java trunk/freenet/src/freenet/io/comm/Peer.java trunk/freenet/src/freenet/support/BitArray.java trunk/freenet/src/freenet/support/Buffer.java trunk/freenet/src/freenet/support/Serializer.java trunk/freenet/src/freenet/support/ShortBuffer.java Log: Fix #2270: Performance, CPU usage on idle node - Use ByteBufferInputStream - Relax DataInputStream to DataInput in some classes Modified: trunk/freenet/src/freenet/io/comm/FreenetInetAddress.java =================================================================== --- trunk/freenet/src/freenet/io/comm/FreenetInetAddress.java 2008-05-09 13:15:41 UTC (rev 19874) +++ trunk/freenet/src/freenet/io/comm/FreenetInetAddress.java 2008-05-09 14:28:23 UTC (rev 19875) @@ -3,7 +3,7 @@ * http://www.gnu.org/ for further details of the GPL. */ package freenet.io.comm; -import java.io.DataInputStream; +import java.io.DataInput; import java.io.DataOutputStream; import java.io.IOException; import java.net.InetAddress; @@ -32,7 +32,7 @@ /** * Create from serialized form on a DataInputStream. */ - public FreenetInetAddress(DataInputStream dis) throws IOException { + public FreenetInetAddress(DataInput dis) throws IOException { int firstByte = dis.readUnsignedByte(); byte[] ba; if(firstByte == 255) { @@ -59,7 +59,8 @@ /** * Create from serialized form on a DataInputStream. */ - public FreenetInetAddress(DataInputStream dis, boolean checkHostnameOrIPSyntax) throws HostnameSyntaxException, IOException { + public FreenetInetAddress(DataInput dis, boolean checkHostnameOrIPSyntax) throws HostnameSyntaxException, + IOException { int firstByte = dis.readUnsignedByte(); byte[] ba; if(firstByte == 255) { Modified: trunk/freenet/src/freenet/io/comm/Message.java =================================================================== --- trunk/freenet/src/freenet/io/comm/Message.java 2008-05-09 13:15:41 UTC (rev 19874) +++ trunk/freenet/src/freenet/io/comm/Message.java 2008-05-09 14:28:23 UTC (rev 19875) @@ -19,10 +19,18 @@ package freenet.io.comm; -import java.io.*; +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.EOFException; +import java.io.IOException; import java.lang.ref.WeakReference; -import java.util.*; +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.Vector; +import freenet.support.ByteBufferInputStream; import freenet.support.Fields; import freenet.support.Logger; import freenet.support.Serializer; @@ -46,17 +54,16 @@ final int _receivedByteCount; public static Message decodeMessageFromPacket(byte[] buf, int offset, int length, PeerContext peer, int overhead) { - DataInputStream dis - = new DataInputStream(new ByteArrayInputStream(buf, - offset, length)); - return decodeMessage(dis, peer, length + overhead, true, false); + ByteBufferInputStream bb = new ByteBufferInputStream(buf, offset, length); + return decodeMessage(bb, peer, length + overhead, true, false); } - public static Message decodeMessage(DataInputStream dis, PeerContext peer, int recvByteCount, boolean mayHaveSubMessages, boolean inSubMessage) { + private static Message decodeMessage(ByteBufferInputStream bb, PeerContext peer, int recvByteCount, + boolean mayHaveSubMessages, boolean inSubMessage) { boolean logMINOR = Logger.shouldLog(Logger.MINOR, Message.class); MessageType mspec; try { - mspec = MessageType.getSpec(new Integer(dis.readInt())); + mspec = MessageType.getSpec(new Integer(bb.readInt())); } catch (IOException e1) { if(Logger.shouldLog(Logger.DEBUG, Message.class)) Logger.minor(Message.class,"Failed to read message type: "+e1, e1); @@ -73,25 +80,27 @@ String name = (String) i.next(); Class type = (Class) mspec.getFields().get(name); if (type.equals(LinkedList.class)) { // Special handling for LinkedList to deal with element type - m.set(name, Serializer.readListFromDataInputStream((Class) mspec.getLinkedListTypes().get(name), dis)); + m.set(name, Serializer + .readListFromDataInputStream((Class) mspec.getLinkedListTypes().get(name), bb)); } else { - m.set(name, Serializer.readFromDataInputStream(type, dis)); + m.set(name, Serializer.readFromDataInputStream(type, bb)); } - } - if(mayHaveSubMessages) { - while(true) { - DataInputStream dis2; + } + if (mayHaveSubMessages) { + while (bb.remaining() > 2) { // sizeof(unsigned short) == 2 + ByteBufferInputStream bb2; try { - int size = dis.readUnsignedShort(); - byte[] buf = new byte[size]; - dis.readFully(buf); - dis2 = new DataInputStream(new ByteArrayInputStream(buf)); + int size = bb.readUnsignedShort(); + if (bb.remaining() < size) + return m; + + bb2 = bb.slice(size); } catch (EOFException e) { if(logMINOR) Logger.minor(Message.class, "No submessages, returning: "+m); return m; } try { - Message subMessage = decodeMessage(dis2, peer, 0, false, true); + Message subMessage = decodeMessage(bb2, peer, 0, false, true); if(subMessage == null) return m; if(logMINOR) Logger.minor(Message.class, "Adding submessage: "+subMessage); m.addSubMessage(subMessage); Modified: trunk/freenet/src/freenet/io/comm/Peer.java =================================================================== --- trunk/freenet/src/freenet/io/comm/Peer.java 2008-05-09 13:15:41 UTC (rev 19874) +++ trunk/freenet/src/freenet/io/comm/Peer.java 2008-05-09 14:28:23 UTC (rev 19875) @@ -19,6 +19,7 @@ package freenet.io.comm; +import java.io.DataInput; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; @@ -50,13 +51,13 @@ this(InetAddress.getLocalHost(), 0); } - public Peer(DataInputStream dis) throws IOException { + public Peer(DataInput dis) throws IOException { addr = new FreenetInetAddress(dis); _port = dis.readInt(); if(_port > 65535 || _port < 0) throw new IOException("bogus port"); } - public Peer(DataInputStream dis, boolean checkHostnameOrIPSyntax) throws HostnameSyntaxException, IOException { + public Peer(DataInput dis, boolean checkHostnameOrIPSyntax) throws HostnameSyntaxException, IOException { addr = new FreenetInetAddress(dis, checkHostnameOrIPSyntax); _port = dis.readInt(); if(_port > 65535 || _port < 0) throw new IOException("bogus port"); Modified: trunk/freenet/src/freenet/support/BitArray.java =================================================================== --- trunk/freenet/src/freenet/support/BitArray.java 2008-05-09 13:15:41 UTC (rev 19874) +++ trunk/freenet/src/freenet/support/BitArray.java 2008-05-09 14:28:23 UTC (rev 19875) @@ -19,7 +19,9 @@ package freenet.support; -import java.io.*; +import java.io.DataInput; +import java.io.DataOutputStream; +import java.io.IOException; import freenet.io.WritableToDataOutputStream; @@ -33,13 +35,13 @@ /** * This constructor does not check for unacceptable sizes, and should only be used on trusted data. */ - public BitArray(DataInputStream dis) throws IOException { + public BitArray(DataInput dis) throws IOException { _size = dis.readInt(); _bits = new byte[(_size / 8) + (_size % 8 == 0 ? 0 : 1)]; dis.readFully(_bits); } - public BitArray(DataInputStream dis, int maxSize) throws IOException { + public BitArray(DataInput dis, int maxSize) throws IOException { _size = dis.readInt(); if (_size<=0 || _size>maxSize) throw new IOException("Unacceptable bitarray size: "+_size); Modified: trunk/freenet/src/freenet/support/Buffer.java =================================================================== --- trunk/freenet/src/freenet/support/Buffer.java 2008-05-09 13:15:41 UTC (rev 19874) +++ trunk/freenet/src/freenet/support/Buffer.java 2008-05-09 14:28:23 UTC (rev 19875) @@ -19,8 +19,10 @@ package freenet.support; -import java.io.*; -import java.util.*; +import java.io.DataInput; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.Arrays; import freenet.io.WritableToDataOutputStream; @@ -45,7 +47,7 @@ * @param dis * @throws IOException */ - public Buffer(DataInputStream dis) throws IOException { + public Buffer(DataInput dis) throws IOException { _data = new byte[dis.readInt()]; _length = _data.length; _start = 0; Added: trunk/freenet/src/freenet/support/ByteBufferInputStream.java =================================================================== --- trunk/freenet/src/freenet/support/ByteBufferInputStream.java (rev 0) +++ trunk/freenet/src/freenet/support/ByteBufferInputStream.java 2008-05-09 14:28:23 UTC (rev 19875) @@ -0,0 +1,202 @@ +/* This code is part of Freenet. It is distributed under the GNU General + * Public License, version 2 (or at your option any later version). See + * http://www.gnu.org/ for further details of the GPL. */ +package freenet.support; + +import java.io.DataInput; +import java.io.DataInputStream; +import java.io.EOFException; +import java.io.IOException; +import java.io.InputStream; +import java.nio.BufferUnderflowException; +import java.nio.ByteBuffer; + +/** + * @author sdiz + */ +public class ByteBufferInputStream extends InputStream implements DataInput { + protected ByteBuffer buf; + + public ByteBufferInputStream(byte[] array) { + this(array, 0, array.length); + } + + public ByteBufferInputStream(byte[] array, int offset, int length) { + this(ByteBuffer.wrap(array, offset, length)); + } + public ByteBufferInputStream(ByteBuffer buf) { + this.buf = buf; + } + + public int read() throws IOException { + try { + return buf.get() & Integer.MAX_VALUE; + } catch (BufferUnderflowException e) { + return -1; + } + } + + + public int remaining() { + return buf.remaining(); + } + + public boolean readBoolean() throws IOException { + try { + return buf.get() != 0; + } catch (BufferUnderflowException e) { + EOFException ioe = new EOFException(); + ioe.initCause(e); + throw ioe; + } + } + + public byte readByte() throws IOException { + try { + return buf.get(); + } catch (BufferUnderflowException e) { + EOFException ioe = new EOFException(); + ioe.initCause(e); + throw ioe; + } + } + + public char readChar() throws IOException { + try { + return buf.getChar(); + } catch (BufferUnderflowException e) { + EOFException ioe = new EOFException(); + ioe.initCause(e); + throw ioe; + } + } + + public double readDouble() throws IOException { + try { + return buf.getDouble(); + } catch (BufferUnderflowException e) { + EOFException ioe = new EOFException(); + ioe.initCause(e); + throw ioe; + } + } + + public float readFloat() throws IOException { + try { + return buf.getFloat(); + } catch (BufferUnderflowException e) { + EOFException ioe = new EOFException(); + ioe.initCause(e); + throw ioe; + } + } + + public void readFully(byte[] b) throws IOException { + try { + buf.get(b); + } catch (BufferUnderflowException e) { + EOFException ioe = new EOFException(); + ioe.initCause(e); + throw ioe; + } + } + + public void readFully(byte[] b, int off, int len) throws IOException { + try { + buf.get(b, off, len); + } catch (BufferUnderflowException e) { + EOFException ioe = new EOFException(); + ioe.initCause(e); + throw ioe; + } + } + + public int readInt() throws IOException { + try { + return buf.getInt(); + } catch (BufferUnderflowException e) { + EOFException ioe = new EOFException(); + ioe.initCause(e); + throw ioe; + } + } + + public long readLong() throws IOException { + try { + return buf.getLong(); + } catch (BufferUnderflowException e) { + EOFException ioe = new EOFException(); + ioe.initCause(e); + throw ioe; + } + } + + public short readShort() throws IOException { + try { + return buf.getShort(); + } catch (BufferUnderflowException e) { + EOFException ioe = new EOFException(); + ioe.initCause(e); + throw ioe; + } + } + + + public int readUnsignedByte() throws IOException { + try { + return buf.get() & Integer.MAX_VALUE; + } catch (BufferUnderflowException e) { + EOFException ioe = new EOFException(); + ioe.initCause(e); + throw ioe; + } + } + + public int readUnsignedShort() throws IOException { + try { + return buf.getShort() & Integer.MAX_VALUE; + } catch (BufferUnderflowException e) { + EOFException ioe = new EOFException(); + ioe.initCause(e); + throw ioe; + } + } + + public int skipBytes(int n) throws IOException { + int skip = Math.min(n, buf.remaining()); + buf.position(buf.position() + skip); + return skip; + } + + public String readUTF() throws IOException { + return DataInputStream.readUTF(this); + } + /** + * @deprecated {@link DataInputStream#readLine()} is deprecated, so why not? + */ + public String readLine() throws IOException { + // hmmmm bad + return new DataInputStream(this).readLine(); + } + + /** + * Slice a piece of ByteBuffer into a new ByteBufferInputStream + * + * @param size + */ + public ByteBufferInputStream slice(int size) throws IOException { + try { + ByteBuffer bf2 = buf.slice(); + bf2.limit(size); + + skip(size); + + return new ByteBufferInputStream(bf2); + } catch (BufferUnderflowException e) { + EOFException ioe = new EOFException(); + ioe.initCause(e); + throw ioe; + } + } + +} Modified: trunk/freenet/src/freenet/support/Serializer.java =================================================================== --- trunk/freenet/src/freenet/support/Serializer.java 2008-05-09 13:15:41 UTC (rev 19874) +++ trunk/freenet/src/freenet/support/Serializer.java 2008-05-09 14:28:23 UTC (rev 19875) @@ -19,7 +19,7 @@ package freenet.support; -import java.io.DataInputStream; +import java.io.DataInput; import java.io.DataOutputStream; import java.io.IOException; import java.util.Iterator; @@ -44,7 +44,7 @@ public static final String VERSION = "$Id: Serializer.java,v 1.5 2005/09/15 18:16:04 amphibian Exp $"; public static final int MAX_BITARRAY_SIZE = 2048*8; - public static List readListFromDataInputStream(Class elementType, DataInputStream dis) throws IOException { + public static List readListFromDataInputStream(Class elementType, DataInput dis) throws IOException { LinkedList ret = new LinkedList(); int length = dis.readInt(); for (int x = 0; x < length; x++) { @@ -53,18 +53,16 @@ return ret; } - public static Object readFromDataInputStream(Class type, DataInputStream dis) throws IOException { + public static Object readFromDataInputStream(Class type, DataInput dis) throws IOException { if (type.equals(Boolean.class)) { - int bool=dis.read(); + int bool = dis.readByte(); if (bool==1) return Boolean.TRUE; if (bool==0) return Boolean.FALSE; throw new IOException("Boolean is non boolean value: "+bool); } else if (type.equals(Byte.class)) { - int b=dis.read(); - if (b<0) - throw new IOException(); + int b = dis.readByte(); return new Byte((byte)b); } else if (type.equals(Short.class)) { return new Short(dis.readShort()); Modified: trunk/freenet/src/freenet/support/ShortBuffer.java =================================================================== --- trunk/freenet/src/freenet/support/ShortBuffer.java 2008-05-09 13:15:41 UTC (rev 19874) +++ trunk/freenet/src/freenet/support/ShortBuffer.java 2008-05-09 14:28:23 UTC (rev 19875) @@ -41,7 +41,7 @@ * @param dis * @throws IOException */ - public ShortBuffer(DataInputStream dis) throws IOException { + public ShortBuffer(DataInput dis) throws IOException { _data = new byte[dis.readShort()]; _length = (short)_data.length; _start = 0;
