You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by pr...@apache.org on 2006/05/15 21:38:37 UTC

svn commit: r406727 - /directory/trunks/mina/core/src/main/java/org/apache/mina/common/PooledByteBufferAllocator.java

Author: proyal
Date: Mon May 15 12:38:36 2006
New Revision: 406727

URL: http://svn.apache.org/viewcvs?rev=406727&view=rev
Log:
DIRMINA-216 - If an OOM is received when expanding a direct buffer, turn it into a heap buffer

Modified:
    directory/trunks/mina/core/src/main/java/org/apache/mina/common/PooledByteBufferAllocator.java

Modified: directory/trunks/mina/core/src/main/java/org/apache/mina/common/PooledByteBufferAllocator.java
URL: http://svn.apache.org/viewcvs/directory/trunks/mina/core/src/main/java/org/apache/mina/common/PooledByteBufferAllocator.java?rev=406727&r1=406726&r2=406727&view=diff
==============================================================================
--- directory/trunks/mina/core/src/main/java/org/apache/mina/common/PooledByteBufferAllocator.java (original)
+++ directory/trunks/mina/core/src/main/java/org/apache/mina/common/PooledByteBufferAllocator.java Mon May 15 12:38:36 2006
@@ -29,20 +29,13 @@
 import java.nio.ShortBuffer;
 
 /**
- * A {@link ByteBufferAllocator} which pools allocated buffers.
- * <p>
- * All buffers are allocated with the size of power of 2 (e.g. 16, 32, 64, ...)
- * This means that you cannot simply assume that the actual capacity of the
- * buffer and the capacity you requested are same.
- * </p>
- * <p>
- * This allocator releases the buffers which have not been in use for a certain
- * period.  You can adjust the period by calling {@link #setTimeout(int)}.
- * The default timeout is 1 minute (60 seconds).  To release these buffers
- * periodically, a daemon thread is started when a new instance of the allocator
- * is created.  You can stop the thread by calling {@link #dispose()}.
- * </p>
- * 
+ * A {@link ByteBufferAllocator} which pools allocated buffers. <p> All buffers are allocated with the size of power of
+ * 2 (e.g. 16, 32, 64, ...) This means that you cannot simply assume that the actual capacity of the buffer and the
+ * capacity you requested are same. </p> <p> This allocator releases the buffers which have not been in use for a
+ * certain period.  You can adjust the period by calling {@link #setTimeout(int)}. The default timeout is 1 minute (60
+ * seconds).  To release these buffers periodically, a daemon thread is started when a new instance of the allocator is
+ * created.  You can stop the thread by calling {@link #dispose()}. </p>
+ *
  * @author The Apache Directory Project (mina-dev@directory.apache.org)
  * @version $Rev$, $Date$
  */
@@ -52,30 +45,30 @@
     private static int threadId = 0;
 
     private final Expirer expirer;
-    private final ExpiringStack[] heapBufferStacks = new ExpiringStack[] {
-            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
-            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
-            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
-            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
-            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
-            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
-            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
-            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
-            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
-            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
-            new ExpiringStack(), new ExpiringStack(), };
-    private final ExpiringStack[] directBufferStacks = new ExpiringStack[] {
-            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
-            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
-            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
-            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
-            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
-            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
-            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
-            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
-            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
-            new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
-            new ExpiringStack(), new ExpiringStack(), };
+    private final ExpiringStack[] heapBufferStacks = new ExpiringStack[]{
+        new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
+        new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
+        new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
+        new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
+        new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
+        new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
+        new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
+        new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
+        new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
+        new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
+        new ExpiringStack(), new ExpiringStack(), };
+    private final ExpiringStack[] directBufferStacks = new ExpiringStack[]{
+        new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
+        new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
+        new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
+        new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
+        new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
+        new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
+        new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
+        new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
+        new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
+        new ExpiringStack(), new ExpiringStack(), new ExpiringStack(),
+        new ExpiringStack(), new ExpiringStack(), };
     private int timeout;
     private boolean disposed;
 
@@ -98,8 +91,7 @@
     }
 
     /**
-     * Stops the thread which releases unused buffers and make this allocator
-     * unusable from now on.
+     * Stops the thread which releases unused buffers and make this allocator unusable from now on.
      */
     public void dispose()
     {
@@ -130,24 +122,24 @@
     }
 
     /**
-     * Returns the timeout value of this allocator in seconds. 
+     * Returns the timeout value of this allocator in seconds.
      */
     public int getTimeout()
     {
         return timeout;
     }
-    
+
     /**
-     * Returns the timeout value of this allocator in milliseconds. 
+     * Returns the timeout value of this allocator in milliseconds.
      */
     public long getTimeoutMillis()
     {
         return timeout * 1000L;
     }
-    
+
     /**
      * Sets the timeout value of this allocator in seconds.
-     * 
+     *
      * @param timeout <tt>0</tt> or negative value to disable timeout.
      */
     public void setTimeout( int timeout )
@@ -158,13 +150,13 @@
         }
 
         this.timeout = timeout;
-        
+
         if( timeout > 0 )
         {
-            
+
         }
     }
-    
+
     public ByteBuffer allocate( int capacity, boolean direct )
     {
         ensureNotDisposed();
@@ -176,14 +168,14 @@
 
     private PooledByteBuffer allocateContainer()
     {
-		return new PooledByteBuffer();
+        return new PooledByteBuffer();
     }
-    
+
     private UnexpandableByteBuffer allocate0( int capacity, boolean direct )
     {
-        ExpiringStack[] bufferStacks = direct? directBufferStacks : heapBufferStacks;
+        ExpiringStack[] bufferStacks = direct ? directBufferStacks : heapBufferStacks;
         int idx = getBufferStackIndex( bufferStacks, capacity );
-        ExpiringStack stack = bufferStacks[ idx ];
+        ExpiringStack stack = bufferStacks[idx];
 
         UnexpandableByteBuffer buf;
         synchronized( stack )
@@ -193,29 +185,29 @@
 
         if( buf == null )
         {
-            java.nio.ByteBuffer nioBuf = 
+            java.nio.ByteBuffer nioBuf =
                 direct ? java.nio.ByteBuffer.allocateDirect( MINIMUM_CAPACITY << idx ) :
                 java.nio.ByteBuffer.allocate( MINIMUM_CAPACITY << idx );
             buf = new UnexpandableByteBuffer( nioBuf );
         }
 
         buf.init();
-        
+
         return buf;
     }
-    
+
     private void release0( UnexpandableByteBuffer buf )
     {
-        ExpiringStack[] bufferStacks = buf.buf().isDirect()? directBufferStacks : heapBufferStacks;
-        ExpiringStack stack = bufferStacks[ getBufferStackIndex( bufferStacks, buf.buf().capacity() ) ];
-        
+        ExpiringStack[] bufferStacks = buf.buf().isDirect() ? directBufferStacks : heapBufferStacks;
+        ExpiringStack stack = bufferStacks[getBufferStackIndex( bufferStacks, buf.buf().capacity() )];
+
         synchronized( stack )
         {
             // push back
             stack.push( buf );
         }
     }
-    
+
     public ByteBuffer wrap( java.nio.ByteBuffer nioBuffer )
     {
         ensureNotDisposed();
@@ -233,17 +225,17 @@
         while( size > targetSize )
         {
             targetSize <<= 1;
-            stackIdx ++ ;
+            stackIdx ++;
             if( stackIdx >= bufferStacks.length )
             {
                 throw new IllegalArgumentException(
-                        "Buffer size is too big: " + size );
+                    "Buffer size is too big: " + size );
             }
         }
 
         return stackIdx;
     }
-    
+
     private void ensureNotDisposed()
     {
         if( disposed )
@@ -261,7 +253,7 @@
             super( "PooledByteBufferExpirer-" + threadId++ );
             setDaemon( true );
         }
-        
+
         public void shutdown()
         {
             timeToStop = true;
@@ -272,13 +264,13 @@
                 {
                     join();
                 }
-                catch ( InterruptedException e )
+                catch( InterruptedException e )
                 {
                     //ignore since this is shutdown time
                 }
             }
         }
-        
+
         public void run()
         {
             // Expire unused buffers every seconds
@@ -288,7 +280,7 @@
                 {
                     Thread.sleep( 1000 );
                 }
-                catch ( InterruptedException e )
+                catch( InterruptedException e )
                 {
                     //ignore
                 }
@@ -305,7 +297,7 @@
 
                 for( int i = directBufferStacks.length - 1; i >= 0; i -- )
                 {
-                    ExpiringStack stack = directBufferStacks[ i ];
+                    ExpiringStack stack = directBufferStacks[i];
                     synchronized( stack )
                     {
                         stack.expireBefore( expirationTime );
@@ -314,7 +306,7 @@
 
                 for( int i = heapBufferStacks.length - 1; i >= 0; i -- )
                 {
-                    ExpiringStack stack = heapBufferStacks[ i ];
+                    ExpiringStack stack = heapBufferStacks[i];
                     synchronized( stack )
                     {
                         stack.expireBefore( expirationTime );
@@ -333,7 +325,7 @@
         protected PooledByteBuffer()
         {
         }
-        
+
         public synchronized void init( UnexpandableByteBuffer buf, boolean clear )
         {
             this.buf = buf;
@@ -345,7 +337,7 @@
             autoExpand = false;
             refCount = 1;
         }
-        
+
         public synchronized void acquire()
         {
             if( refCount <= 0 )
@@ -364,11 +356,11 @@
                 {
                     refCount = 0;
                     throw new IllegalStateException(
-                            "Already released buffer.  You released the buffer too many times." );
+                        "Already released buffer.  You released the buffer too many times." );
                 }
 
                 refCount --;
-                if( refCount > 0)
+                if( refCount > 0 )
                 {
                     return;
                 }
@@ -387,43 +379,43 @@
         {
             return buf.buf();
         }
-        
+
         public boolean isDirect()
         {
             return buf.buf().isDirect();
         }
-        
+
         public boolean isReadOnly()
         {
             return buf.buf().isReadOnly();
         }
-        
+
         public boolean isAutoExpand()
         {
             return autoExpand;
         }
-        
+
         public ByteBuffer setAutoExpand( boolean autoExpand )
         {
             this.autoExpand = autoExpand;
             return this;
         }
-        
+
         public boolean isPooled()
         {
             return buf.isPooled();
         }
-        
+
         public void setPooled( boolean pooled )
         {
-            buf.setPooled(pooled);
+            buf.setPooled( pooled );
         }
 
         public int capacity()
         {
             return buf.buf().capacity();
         }
-        
+
         public int position()
         {
             return buf.buf().position();
@@ -487,7 +479,7 @@
         {
             PooledByteBuffer newBuf = allocateContainer();
             newBuf.init(
-                    new UnexpandableByteBuffer( buf.buf().duplicate(), buf ), false );
+                new UnexpandableByteBuffer( buf.buf().duplicate(), buf ), false );
             return newBuf;
         }
 
@@ -495,7 +487,7 @@
         {
             PooledByteBuffer newBuf = allocateContainer();
             newBuf.init(
-                    new UnexpandableByteBuffer( buf.buf().slice(), buf ), false );
+                new UnexpandableByteBuffer( buf.buf().slice(), buf ), false );
             return newBuf;
         }
 
@@ -503,7 +495,7 @@
         {
             PooledByteBuffer newBuf = allocateContainer();
             newBuf.init(
-                    new UnexpandableByteBuffer( buf.buf().asReadOnlyBuffer(), buf ), false );
+                new UnexpandableByteBuffer( buf.buf().asReadOnlyBuffer(), buf ), false );
             return newBuf;
         }
 
@@ -754,48 +746,68 @@
                 int pos = buf.buf().position();
                 int limit = buf.buf().limit();
                 int end = pos + expectedRemaining;
-                if( end > limit ) {
+                if( end > limit )
+                {
                     ensureCapacity( end );
                     buf.buf().limit( end );
                 }
             }
             return this;
         }
-        
+
         public ByteBuffer expand( int pos, int expectedRemaining )
         {
             if( autoExpand )
             {
                 int limit = buf.buf().limit();
                 int end = pos + expectedRemaining;
-                if( end > limit ) {
+                if( end > limit )
+                {
                     ensureCapacity( end );
                     buf.buf().limit( end );
                 }
             }
             return this;
         }
-        
+
         private void ensureCapacity( int requestedCapacity )
         {
             if( requestedCapacity <= buf.buf().capacity() )
             {
                 return;
             }
-            
+
             if( buf.isDerived() )
             {
                 throw new IllegalStateException( "Derived buffers cannot be expanded." );
             }
-            
+
             int newCapacity = MINIMUM_CAPACITY;
             while( newCapacity < requestedCapacity )
             {
                 newCapacity <<= 1;
             }
-            
+
             UnexpandableByteBuffer oldBuf = this.buf;
-            UnexpandableByteBuffer newBuf = allocate0( newCapacity, isDirect() );
+            boolean direct = isDirect();
+            UnexpandableByteBuffer newBuf;
+
+            try
+            {
+                newBuf = allocate0( newCapacity, direct );
+            }
+            catch( OutOfMemoryError e )
+            {
+                if( direct )
+                {
+                    newBuf = allocate0( newCapacity, false );
+                }
+                else
+                {
+                    throw e;
+                }
+            }
+
             newBuf.buf().clear();
             newBuf.buf().order( oldBuf.buf().order() );
 
@@ -823,29 +835,28 @@
             this.buf = buf;
             this.parentBuf = null;
         }
-        
-        protected UnexpandableByteBuffer(
-                java.nio.ByteBuffer buf,
-                UnexpandableByteBuffer parentBuf )
+
+        protected UnexpandableByteBuffer( java.nio.ByteBuffer buf, UnexpandableByteBuffer parentBuf )
         {
             parentBuf.acquire();
             this.buf = buf;
             this.parentBuf = parentBuf;
         }
-        
+
         public void init()
         {
             refCount = 1;
             pooled = true;
         }
-        
+
         public synchronized void acquire()
         {
-            if( isDerived() ) {
+            if( isDerived() )
+            {
                 parentBuf.acquire();
                 return;
             }
-            
+
             if( refCount <= 0 )
             {
                 throw new IllegalStateException( "Already released buffer." );
@@ -856,22 +867,23 @@
 
         public void release()
         {
-            if( isDerived() ) {
+            if( isDerived() )
+            {
                 parentBuf.release();
                 return;
             }
-            
+
             synchronized( this )
             {
                 if( refCount <= 0 )
                 {
                     refCount = 0;
                     throw new IllegalStateException(
-                            "Already released buffer.  You released the buffer too many times." );
+                        "Already released buffer.  You released the buffer too many times." );
                 }
 
                 refCount --;
-                if( refCount > 0)
+                if( refCount > 0 )
                 {
                     return;
                 }
@@ -900,17 +912,17 @@
         {
             return buf;
         }
-        
+
         public boolean isPooled()
         {
             return pooled;
         }
-        
+
         public void setPooled( boolean pooled )
         {
             this.pooled = pooled;
         }
-        
+
         public boolean isDerived()
         {
             return parentBuf != null;