| /* |
| * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| package com.sun.corba.se.impl.transport; |
| |
| import java.nio.ByteBuffer; |
| import java.util.ArrayList; |
| |
| import com.sun.corba.se.spi.orb.ORB; |
| |
| import com.sun.corba.se.pept.transport.ByteBufferPool; |
| |
| /** |
| * @author Charlie Hunt |
| */ |
| |
| public class ByteBufferPoolImpl implements ByteBufferPool |
| { |
| private ORB itsOrb; |
| private int itsByteBufferSize; |
| private ArrayList itsPool; |
| private int itsObjectCounter = 0; |
| private boolean debug; |
| |
| // Construct a ByteBufferPool for a pool of NIO ByteBuffers |
| // of ORB fragment size. |
| public ByteBufferPoolImpl(ORB theORB) |
| { |
| itsByteBufferSize = theORB.getORBData().getGIOPFragmentSize(); |
| itsPool = new ArrayList(); |
| itsOrb = theORB; |
| debug = theORB.transportDebugFlag; |
| } |
| |
| /* |
| * Locations where ByteBuffers are gotten from the pool: |
| * 1. ContactInfoBase.createMessageMediator() |
| * 2. ByteBufferWithInfo.growBuffer() |
| * 3. ByteBufferWithInfo(ORB, BufferManagerWrite) - constructor |
| */ |
| |
| // If the requested ByteBuffer size is less than or equal to |
| // the ORB fragment size, and we have not disabled use of |
| // direct byte buffers (normally for debugging purposes) |
| // then get a DirectByteBuffer from the |
| // pool if there is one, if there is not one in the pool, |
| // then allocate a a DirectByteBuffer of ORB fragment size. |
| // |
| // If the request ByteBuffer size is greater than the ORB fragment |
| // size, allocate a new non-direct ByteBuffer. |
| public ByteBuffer getByteBuffer(int theAskSize) |
| { |
| ByteBuffer abb = null; |
| |
| if ((theAskSize <= itsByteBufferSize) && |
| !itsOrb.getORBData().disableDirectByteBufferUse()) |
| { |
| // check if there's one in the pool, if not allocate one. |
| int poolSize; |
| synchronized (itsPool) |
| { |
| poolSize = itsPool.size(); |
| if (poolSize > 0) |
| { |
| abb = (ByteBuffer)itsPool.remove(poolSize - 1); |
| |
| // clear ByteBuffer before returning it |
| abb.clear(); |
| } |
| } |
| |
| // NOTE: Moved the 'else' part of the above if statement |
| // outside the synchronized block since it is likely |
| // less expensive to check poolSize than to allocate a |
| // DirectByteBuffer in the synchronized block. |
| if (poolSize <= 0) |
| { |
| abb = ByteBuffer.allocateDirect(itsByteBufferSize); |
| } |
| |
| // increment the number of ByteBuffers gotten from pool |
| // IMPORTANT: Since this counter is used only for information |
| // purposes, it does not use synchronized access. |
| itsObjectCounter++; |
| } |
| else |
| { |
| // Requested ByteBuffer size larger than the pool manages. |
| // Just allocate a non-direct ByteBuffer |
| abb = ByteBuffer.allocate(theAskSize); |
| } |
| |
| return abb; |
| } |
| |
| |
| /* |
| * Locations where ByteBuffers are released to the pool: |
| * 1. ByteBufferWithInfo.growBuffer() |
| * 2. BufferManagerWriteCollect.sendMessage() |
| * 3. CDROutputStream_1_0.close() |
| * 4. CDRInputStream_1_0.close() |
| * 5. BufferManagerReadStream.underflow() |
| * 6. BufferManagerWrite.close() |
| * 7. BufferManagerRead.close() |
| * 8. CorbaMessageMediatorImpl.releaseByteBufferToPool() |
| */ |
| |
| // If the ByteBuffer is a DirectByteBuffer, add it to the pool. |
| // Otherwise, set its reference to null since it's not kept in |
| // the pool and caller is saying he/she is done with it. |
| // NOTE: The size of the ByteBuffer is not checked with the |
| // this pool's ByteBuffer size since only DirectByteBuffers |
| // ever allocated. Hence, only DirectByteBuffer are checked |
| // here. An additional check could be added here for that though. |
| public void releaseByteBuffer(ByteBuffer thebb) |
| { |
| if (thebb.isDirect()) |
| { |
| synchronized (itsPool) |
| { |
| // use with debug to determine if byteBuffer is already |
| // in the pool. |
| boolean refInPool = false; |
| int bbAddr = 0; |
| |
| if (debug) |
| { |
| // Check to make sure we don't have 'thebb' reference |
| // already in the pool before adding it. |
| |
| for (int i = 0; i < itsPool.size() && refInPool == false; i++) |
| { |
| ByteBuffer tmpbb = (ByteBuffer)itsPool.get(i); |
| if (thebb == tmpbb) |
| { |
| refInPool = true; |
| bbAddr = System.identityHashCode(thebb); |
| } |
| } |
| |
| } |
| |
| // NOTE: The else part of this if will only get called |
| // if debug = true and refInPool = true, see logic above. |
| if (refInPool == false || debug == false) |
| { |
| // add ByteBuffer back to the pool |
| itsPool.add(thebb); |
| } |
| else // otherwise, log a stack trace with duplicate message |
| { |
| String threadName = Thread.currentThread().getName(); |
| Throwable t = |
| new Throwable(threadName + |
| ": Duplicate ByteBuffer reference (" + |
| bbAddr + ")"); |
| t.printStackTrace(System.out); |
| } |
| } |
| |
| // decrement the count of ByteBuffers released |
| // IMPORTANT: Since this counter is used only for information |
| // purposes, it does not use synchronized access. |
| itsObjectCounter--; |
| } |
| else |
| { |
| // ByteBuffer not pooled nor needed |
| thebb = null; |
| } |
| } |
| |
| |
| // Get a count of the outstanding allocated DirectByteBuffers. |
| // (Those allocated and have not been returned to the pool). |
| // IMPORTANT: Since this counter is used only for information |
| // purposes, it does not use synchronized access. |
| public int activeCount() |
| { |
| return itsObjectCounter; |
| } |
| } |
| |
| // End of file. |