Commits

Ning Sun  committed e347350

Add new ExtensibleBuffer wraps ByteBuffer, change protocol argument to byte array.

  • Participants
  • Parent commits 456061d

Comments (0)

Files changed (12)

File src/main/java/info/sunng/soldat/Client.java

 package info.sunng.soldat;
 
 import info.sunng.soldat.engines.Transport;
-import java.nio.ByteBuffer;
 import java.nio.channels.SelectionKey;
 import java.util.HashMap;
 import java.util.Map;
  *
  */
 public class Client {
-    public static int DEFAULT_BUFFER_SIZE = 50 * 1024;
     public static int MAX_RETRY = 5;
     public static int MAX_READ = 2 * 1000 * 1000;
 

File src/main/java/info/sunng/soldat/ExtensibleBuffer.java

+/*
+ *  Copyright (c) 2011 Sun Ning <classicning@gmail.com>
+ *  All rights reserved.
+ * 
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *  * Neither the name of the project nor the
+ *    names of its contributors may be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ * 
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ *  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *  DISCLAIMED. IN NO EVENT SHALL Sun Ning BE LIABLE FOR ANY
+ *  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 
+ */
+package info.sunng.soldat;
+
+import java.nio.ByteBuffer;
+
+/**
+ *
+ * @author Sun Ning
+ *
+ */
+public class ExtensibleBuffer {
+    
+    public static final int DEFAULT_BUFFER_SIZE = 4*1024;
+    
+    private ByteBuffer backend;
+    
+    /**
+     * 
+     * @param bytes
+     * @return 
+     */
+    public static ExtensibleBuffer wrap(byte[] bytes) {
+        ByteBuffer buffer = ByteBuffer.wrap(bytes);
+        return new ExtensibleBuffer(buffer);
+    }
+    
+    public static ExtensibleBuffer allocate(int size) {
+        ByteBuffer buffer  = ByteBuffer.allocate(size);
+        return new ExtensibleBuffer(buffer);
+    }
+    
+    public ExtensibleBuffer() {
+        this.backend = ByteBuffer.allocate(DEFAULT_BUFFER_SIZE);
+    }
+    
+    public ExtensibleBuffer(ByteBuffer backend) {
+        this.backend = backend;
+    }
+    
+    public void put(ByteBuffer buffer) {
+        buffer.flip();
+        if (this.backend.remaining() < buffer.limit()) {
+            int newSize = Math.max(this.backend.limit(), buffer.limit()) << 1;
+            ByteBuffer extendedBuffer = ByteBuffer.allocate(newSize);
+            
+            extendedBuffer.put(backend);
+            extendedBuffer.put(buffer);
+            
+            this.backend = extendedBuffer;
+        } else {
+            this.backend.put(buffer);
+        }
+    }
+    
+    public void flip() {
+        this.backend.flip();
+    }
+    
+    public void rewind() {
+        this.backend.rewind();
+    }
+    
+    public byte[] toBytes() {
+        rewind();
+        byte[] bytes = new byte[this.backend.limit()];
+        this.backend.get(bytes);
+        return bytes;
+    }
+    
+}

File src/main/java/info/sunng/soldat/Protocol.java

      * @param buffer
      * @return
      */
-    public boolean isMessageCompleted(ByteBuffer buffer);
+    public boolean isMessageCompleted(byte[] buffer);
     
 }

File src/main/java/info/sunng/soldat/engines/PacketReader.java

 package info.sunng.soldat.engines;
 
 import info.sunng.soldat.Client;
+import info.sunng.soldat.ExtensibleBuffer;
 import info.sunng.soldat.util.NIOUtils;
 import java.io.IOException;
 import java.nio.ByteBuffer;
      * @throws IOException
      */
     public int read() throws IOException {
-        ByteBuffer clientBuffer = ByteBuffer.allocate(Client.DEFAULT_BUFFER_SIZE);
+        ExtensibleBuffer clientBuffer = new ExtensibleBuffer();
         
         client.setRead(0);
         ByteBuffer buffer = ByteBuffer.allocate(1024*4);
                 return -1;
             }
 
-            buffer.flip();
-
-            // not enough space in main buffer
-            if (clientBuffer.remaining() < read){
-                // double size
-                int newSize = client.getRead() << 1;
-                ByteBuffer newBuffer = ByteBuffer.allocate(newSize);
-                newBuffer.put(clientBuffer);
-                newBuffer.put(buffer);
-                clientBuffer = newBuffer;
-            } else {
-                // enough space, just put
-                clientBuffer.put(buffer);
-            }
+            clientBuffer.put(buffer);
 
             buffer.clear();
 
             clientBuffer.flip();
-            if (client.getProtocol().isMessageCompleted(clientBuffer)) {
-                clientBuffer.rewind();
-                byte[] data = new byte[clientBuffer.limit()];
-                clientBuffer.get(data);
-                clientBuffer = ByteBuffer.wrap(data);
-
+            if (client.getProtocol().isMessageCompleted(clientBuffer.toBytes())) {
+                
                 if(logger.isTraceEnabled()){
                     logger.trace("packet read complete");
                 }
 
-                clientBuffer.rewind();
-                client.setInput(clientBuffer);
+                client.setInput(clientBuffer.toBytes());
                 
                 return client.getRead();
             }

File src/main/java/info/sunng/soldat/examples/echoserver/EchoHandler.java

     @Override
     public void onMessageComplete(Client client) {
         try {
-            ByteBuffer request = (ByteBuffer)client.getInput();
-            String content = new String(request.array(), "UTF-8");
+            byte[] request = (byte[])client.getInput();
+            String content = new String(request, "UTF-8");
             if (logger.isDebugEnabled()){
                 logger.debug(content);
             }

File src/main/java/info/sunng/soldat/examples/echoserver/EchoProtocol.java

 public class EchoProtocol implements Protocol {
 
     @Override
-    public boolean isMessageCompleted(ByteBuffer buffer) {
+    public boolean isMessageCompleted(byte[] buffer) {
 
-        int len = buffer.limit();
+        int len = buffer.length;
+        System.out.println(new String(buffer));
 
         if (len < 2) {
             return false;
         } else {
-            char l1 = (char)buffer.get(len - 2);
-            char l2 = (char)buffer.get(len - 1);
+            char l1 = (char)buffer[len - 2];
+            char l2 = (char)buffer[len - 1];
             return l1 == '\r' && l2 == '\n';
         }
 

File src/main/java/info/sunng/soldat/examples/http/HttpMessage.java

 package info.sunng.soldat.examples.http;
 
 import info.sunng.soldat.util.StringUtils;
+import java.io.UnsupportedEncodingException;
 import java.nio.ByteBuffer;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 /**
  * 
  */
 public class HttpMessage {
 
-    byte[] data;
     String httpMessage;
+    
+    public HttpMessage(byte[] buffer ){
+        try {
+            httpMessage = new String(buffer, "utf8");
+        } catch (UnsupportedEncodingException ex) {
+            
+        }
+    }
 
     public HttpMessage(ByteBuffer buffer) {
-        data = new byte[buffer.limit()];
+        byte[] data = new byte[buffer.limit()];
         buffer.get(data);
-        httpMessage = new String(data);
-
+        try {
+            httpMessage = new String(data, "utf8");
+        } catch (UnsupportedEncodingException ex) {
+            
+        }
     }
 
     public String getRequestURI() {

File src/main/java/info/sunng/soldat/examples/http/HttpProtocol.java

     }
 
     @Override
-    public boolean isMessageCompleted(ByteBuffer buffer) {
+    public boolean isMessageCompleted(byte[] buffer) {
         HttpMessage p = new HttpMessage(buffer);
         if (p.isHeaderComplete()) {
             String lengthText  =  p.getHeaders().get("Content-Length");

File src/main/java/info/sunng/soldat/examples/http/HttpServerHandler.java

     @Override
     public void onMessageComplete(Client client) {
 
-        ByteBuffer requestBuffer = (ByteBuffer)client.getInput();
+        byte[] requestBuffer = (byte[])client.getInput();
         HttpMessage message  = new HttpMessage(requestBuffer);
         client.setAttachment(message);
 

File src/main/java/info/sunng/soldat/examples/timeserver/TimeHandler.java

         try {
             String data = new Date().toString()+"\r\n";
             ByteBuffer buffer = ByteBuffer.wrap(data.getBytes("UTF-8"));
-            client.setInput(buffer);
+            client.setOutput(buffer);
         } catch (Exception e) {
             
         }

File src/main/java/info/sunng/soldat/examples/timeserver/TimeProtocol.java

 public class TimeProtocol implements Protocol {
 
     @Override
-    public boolean isMessageCompleted(ByteBuffer buffer) {
+    public boolean isMessageCompleted(byte[] buffer) {
 
-        int length = buffer.limit();
+        int length = buffer.length;
 
         if (length < 2) {
             return false;
         } else {
-            char l1 = (char)buffer.get(length - 2);
-            char l2 = (char)buffer.get(length - 1);
+            char l1 = (char)buffer[length - 2];
+            char l2 = (char)buffer[length - 1];
             return l1 == '\r' && l2 == '\n';
         }
 

File src/main/resources/log4j.properties

-log4j.rootLogger=INFO, CONSOLE
+log4j.rootLogger=DEBUG, CONSOLE
 log4j.addivity.org.apache=true
 log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
 log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout