blob: 91b26c411ee8c40677a1197672d280c6aaceef2b [file] [log] [blame]
/*
* 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.