I noticed that this bug was marked RESOLVED/LATER and was wondering if there was any 
way to get this into 3.2.2 since that is the version that is closest to being 
released.  I've already found 2 ways to fix this issue but am willing to abide by the 
groups decision and concentrate on getting this into the 3.3 release instead.
The 2 ways to fix this are:

1.  In BufferedServletInputStream, implement an available() method that returns limit 
- bytesRead or 0 whichever is greater.  The limit class variable is set to the value 
of the Content-Length header and bytesRead is the number of bytes read since limit was 
set (see the attached diff1.txt).  This is the easy fix but doesn't address the 
feature of available that says it will return the number of bytes that can be read 
"without blocking".  Obviously, if there is a large amount of data, a read will most 
likely block at some point depending on how much is asked for, however this prevents a 
condition where one of the adapters returns 0 because a read hasn't actually been 
requested from the webserver.

2.  Update BufferedServletInputStream to call reqA.available and then update the 
following files to provide this interface:
  Request.java
  RequestImpl.java
  HttpRequestAdapter.java
  Ajp12ConnectionHandler.java
  Ajp13ConnectorRequest.java
  JNIConnectionHandler.java
  MsgConnector.java
  TcpConnector.java
Each of these classes would need to provide an appropriate available() method.  I've 
also done the work on these files as well (see the attached diff2.txt) but noticed 
that since some of the protocols (particularly AJP13) actually have to request a read 
to fill their internal buffer, the adapter (i.e. Ajp13ConnectorRequest.java) will 
return a 0 if doRead is called and it exactly empties the internal buffer.  Also the 
JNIRequestAdapter (in JNIConnectionHandler.java) makes a native call back into the 
webserver to do the reads and so available is implemented similar to #1 above; it just 
returns the max of contentLength - bytesRead or 0.  This was because I'm not sure of a 
way to imp

After testing both of these, implementation 1 is actually faster and more reliable.  
Typically if someone is calling available and they get back a 0, they would block the 
thread anyways and so it makes some sense to let it block on the read plus it gets 
around the issue of an adapter requiring one of it's read methods to be called to 
actually have something available.

Any response positive or negative would be appreciated so that I know where to focus 
my energy (i.e. 3.2.2 or 3.3).



Index: BufferedServletInputStream.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-tomcat/src/share/org/apache/tomcat/core/Attic/BufferedServletInputStream.java,v
retrieving revision 1.8
diff -u -r1.8 BufferedServletInputStream.java
--- BufferedServletInputStream.java     2000/05/26 17:32:04     1.8
+++ BufferedServletInputStream.java     2001/03/21 21:03:59
@@ -151,6 +151,10 @@
        }
     }
     
+    public int available() throws IOException {
+        return Math.max((limit - bytesRead), 0);
+    }
+    
 
 //     /**
 //      * @deprecated Not part of Servlet API, without it we can avoid a lot of GC.
Index: BufferedServletInputStream.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-tomcat/src/share/org/apache/tomcat/core/Attic/BufferedServletInputStream.java,v
retrieving revision 1.8
diff -u -r1.8 BufferedServletInputStream.java
--- BufferedServletInputStream.java     2000/05/26 17:32:04     1.8
+++ BufferedServletInputStream.java     2001/03/21 21:04:23
@@ -151,6 +151,10 @@
        }
     }
     
+    public int available() throws IOException {
+        return reqA.available();
+    }
+    
 
 //     /**
 //      * @deprecated Not part of Servlet API, without it we can avoid a lot of GC.


Index: Request.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-tomcat/src/share/org/apache/tomcat/core/Request.java,v
retrieving revision 1.46
diff -u -r1.46 Request.java
--- Request.java        2000/06/22 19:49:35     1.46
+++ Request.java        2001/03/21 21:05:31
@@ -274,6 +274,9 @@
 
     public  int doRead( byte b[], int off, int len ) throws IOException;
 
+    // provide a way to overload available from InputStream
+    public int available() throws IOException;
+
     // -------------------- Internal methods --------------------
     /** Support for "pools"
      */


Index: RequestImpl.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-tomcat/src/share/org/apache/tomcat/core/Attic/RequestImpl.java,v
retrieving revision 1.52.2.7
diff -u -r1.52.2.7 RequestImpl.java
--- RequestImpl.java    2001/03/15 19:00:37     1.52.2.7
+++ RequestImpl.java    2001/03/21 21:05:41
@@ -818,6 +818,11 @@
        return -1;
     }
 
+    // provide a way to overload available from InputStream
+    public int available() throws IOException {
+        return 0;
+    }
+
     // -------------------- "cooked" info --------------------
     // Hints = return null if you don't know,
     // and Tom will find the value. You can also use the static
 

Index: HttpRequestAdapter.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-tomcat/src/share/org/apache/tomcat/service/http/Attic/HttpRequestAdapter.java,v
retrieving revision 1.16.2.6
diff -u -r1.16.2.6 HttpRequestAdapter.java
--- HttpRequestAdapter.java     2001/01/13 18:36:27     1.16.2.6
+++ HttpRequestAdapter.java     2001/03/21 21:10:44
@@ -119,6 +119,11 @@
        return sin.read(b, off, len);
     }
 
+    // provide a way to overload available from InputStream
+    public int available() throws IOException {
+        return Math.max(sin.available(), 0);
+    }
+
     public void readNextRequest(Response response) throws IOException {
 
        // Odd, but works: we use the ServletInputStream, which uses doRead.
 

Index: Ajp12ConnectionHandler.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-tomcat/src/share/org/apache/tomcat/service/connector/Attic/Ajp12ConnectionHandler.java,v
retrieving revision 1.28.2.2
diff -u -r1.28.2.2 Ajp12ConnectionHandler.java
--- Ajp12ConnectionHandler.java 2000/11/10 06:42:51     1.28.2.2
+++ Ajp12ConnectionHandler.java 2001/03/21 21:17:19
@@ -193,6 +193,10 @@
        return ajpin.read(b,off,len);
     }
 
+    public int available() throws IOException {
+        return Math.max(ajpin.available(), 0);
+    }
+
     void log( String s ) {
        contextM.log( s );
     }


Index: Ajp13ConnectorRequest.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-tomcat/src/share/org/apache/tomcat/service/connector/Attic/Ajp13ConnectorRequest.java,v
retrieving revision 1.5.2.5
diff -u -r1.5.2.5 Ajp13ConnectorRequest.java
--- Ajp13ConnectorRequest.java  2001/02/14 22:19:55     1.5.2.5
+++ Ajp13ConnectorRequest.java  2001/03/21 21:14:39
@@ -288,6 +288,10 @@
        return len - toCopy;
     }
     
+    public int available() throws IOException {
+        return Math.max((blen - pos) + con.available(), 0);
+    }
+
     public void recycle() 
     {
         super.recycle();


Index: JNIConnectionHandler.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-tomcat/src/share/org/apache/tomcat/service/connector/Attic/JNIConnectionHandler.java,v
retrieving revision 1.9.2.2
diff -u -r1.9.2.2 JNIConnectionHandler.java
--- JNIConnectionHandler.java   2000/12/12 09:41:44     1.9.2.2
+++ JNIConnectionHandler.java   2001/03/21 21:15:16
@@ -213,6 +213,7 @@
     JNIConnectionHandler h;
     long s;
     long l;
+    int bytesRead;
 
     public int doRead() throws IOException {
         byte []b = new byte[1];
@@ -234,7 +235,16 @@
                    Thread.currentThread().yield();
                }
            }
+        
+        if (contentLength > 0)
+            bytesRead += rc;
+
            return rc;
+    }
+
+    // provide a way to overload available from InputStream
+    public int available() throws IOException {
+        return Math.max(contentLength - bytesRead, 0);
     }
 
     public JNIRequestAdapter(ContextManager cm,


Index: MsgConnector.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-tomcat/src/share/org/apache/tomcat/service/connector/Attic/MsgConnector.java,v
retrieving revision 1.5.2.1
diff -u -r1.5.2.1 MsgConnector.java
--- MsgConnector.java   2000/12/12 09:41:44     1.5.2.1
+++ MsgConnector.java   2001/03/21 21:15:45
@@ -84,4 +84,8 @@
     public int receive(MsgBuffer msg) throws IOException;
 
     public void close() throws IOException;
+
+    // provide a way to overload available from InputStream
+    public int available() throws IOException;
 }
+


Index: TcpConnector.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-tomcat/src/share/org/apache/tomcat/service/connector/Attic/TcpConnector.java,v
retrieving revision 1.2.2.2
diff -u -r1.2.2.2 TcpConnector.java
--- TcpConnector.java   2000/12/12 09:41:44     1.2.2.2
+++ TcpConnector.java   2001/03/21 21:16:01
@@ -175,4 +175,14 @@
     in.close();
     }
     }
+
+    // provide a way to overload available from InputStream
+    public int available() throws IOException {
+        if (null != in) {
+            System.out.println("in.available() = " + in.available());
+            return in.available();
+        }
+        else
+            return 0;
+    }
 }

Reply via email to