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;


Reply via email to