1/* 2 * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package com.sun.corba.se.impl.transport; 27 28import java.nio.ByteBuffer; 29import java.util.ArrayList; 30 31import com.sun.corba.se.spi.orb.ORB; 32 33import com.sun.corba.se.pept.transport.ByteBufferPool; 34 35/** 36 * @author Charlie Hunt 37 */ 38 39public class ByteBufferPoolImpl implements ByteBufferPool 40{ 41 private ORB itsOrb; 42 private int itsByteBufferSize; 43 private ArrayList itsPool; 44 private int itsObjectCounter = 0; 45 private boolean debug; 46 47 // Construct a ByteBufferPool for a pool of NIO ByteBuffers 48 // of ORB fragment size. 49 public ByteBufferPoolImpl(ORB theORB) 50 { 51 itsByteBufferSize = theORB.getORBData().getGIOPFragmentSize(); 52 itsPool = new ArrayList(); 53 itsOrb = theORB; 54 debug = theORB.transportDebugFlag; 55 } 56 57 /* 58 * Locations where ByteBuffers are gotten from the pool: 59 * 1. ContactInfoBase.createMessageMediator() 60 * 2. ByteBufferWithInfo.growBuffer() 61 * 3. ByteBufferWithInfo(ORB, BufferManagerWrite) - constructor 62 */ 63 64 // If the requested ByteBuffer size is less than or equal to 65 // the ORB fragment size, and we have not disabled use of 66 // direct byte buffers (normally for debugging purposes) 67 // then get a DirectByteBuffer from the 68 // pool if there is one, if there is not one in the pool, 69 // then allocate a a DirectByteBuffer of ORB fragment size. 70 // 71 // If the request ByteBuffer size is greater than the ORB fragment 72 // size, allocate a new non-direct ByteBuffer. 73 public ByteBuffer getByteBuffer(int theAskSize) 74 { 75 ByteBuffer abb = null; 76 77 if ((theAskSize <= itsByteBufferSize) && 78 !itsOrb.getORBData().disableDirectByteBufferUse()) 79 { 80 // check if there's one in the pool, if not allocate one. 81 int poolSize; 82 synchronized (itsPool) 83 { 84 poolSize = itsPool.size(); 85 if (poolSize > 0) 86 { 87 abb = (ByteBuffer)itsPool.remove(poolSize - 1); 88 89 // clear ByteBuffer before returning it 90 abb.clear(); 91 } 92 } 93 94 // NOTE: Moved the 'else' part of the above if statement 95 // outside the synchronized block since it is likely 96 // less expensive to check poolSize than to allocate a 97 // DirectByteBuffer in the synchronized block. 98 if (poolSize <= 0) 99 { 100 abb = ByteBuffer.allocateDirect(itsByteBufferSize); 101 } 102 103 // increment the number of ByteBuffers gotten from pool 104 // IMPORTANT: Since this counter is used only for information 105 // purposes, it does not use synchronized access. 106 itsObjectCounter++; 107 } 108 else 109 { 110 // Requested ByteBuffer size larger than the pool manages. 111 // Just allocate a non-direct ByteBuffer 112 abb = ByteBuffer.allocate(theAskSize); 113 } 114 115 return abb; 116 } 117 118 119 /* 120 * Locations where ByteBuffers are released to the pool: 121 * 1. ByteBufferWithInfo.growBuffer() 122 * 2. BufferManagerWriteCollect.sendMessage() 123 * 3. CDROutputStream_1_0.close() 124 * 4. CDRInputStream_1_0.close() 125 * 5. BufferManagerReadStream.underflow() 126 * 6. BufferManagerWrite.close() 127 * 7. BufferManagerRead.close() 128 * 8. CorbaMessageMediatorImpl.releaseByteBufferToPool() 129 */ 130 131 // If the ByteBuffer is a DirectByteBuffer, add it to the pool. 132 // Otherwise, set its reference to null since it's not kept in 133 // the pool and caller is saying he/she is done with it. 134 // NOTE: The size of the ByteBuffer is not checked with the 135 // this pool's ByteBuffer size since only DirectByteBuffers 136 // ever allocated. Hence, only DirectByteBuffer are checked 137 // here. An additional check could be added here for that though. 138 public void releaseByteBuffer(ByteBuffer thebb) 139 { 140 if (thebb.isDirect()) 141 { 142 synchronized (itsPool) 143 { 144 // use with debug to determine if byteBuffer is already 145 // in the pool. 146 boolean refInPool = false; 147 int bbAddr = 0; 148 149 if (debug) 150 { 151 // Check to make sure we don't have 'thebb' reference 152 // already in the pool before adding it. 153 154 for (int i = 0; i < itsPool.size() && refInPool == false; i++) 155 { 156 ByteBuffer tmpbb = (ByteBuffer)itsPool.get(i); 157 if (thebb == tmpbb) 158 { 159 refInPool = true; 160 bbAddr = System.identityHashCode(thebb); 161 } 162 } 163 164 } 165 166 // NOTE: The else part of this if will only get called 167 // if debug = true and refInPool = true, see logic above. 168 if (refInPool == false || debug == false) 169 { 170 // add ByteBuffer back to the pool 171 itsPool.add(thebb); 172 } 173 else // otherwise, log a stack trace with duplicate message 174 { 175 String threadName = Thread.currentThread().getName(); 176 Throwable t = 177 new Throwable(threadName + 178 ": Duplicate ByteBuffer reference (" + 179 bbAddr + ")"); 180 t.printStackTrace(System.out); 181 } 182 } 183 184 // decrement the count of ByteBuffers released 185 // IMPORTANT: Since this counter is used only for information 186 // purposes, it does not use synchronized access. 187 itsObjectCounter--; 188 } 189 else 190 { 191 // ByteBuffer not pooled nor needed 192 thebb = null; 193 } 194 } 195 196 197 // Get a count of the outstanding allocated DirectByteBuffers. 198 // (Those allocated and have not been returned to the pool). 199 // IMPORTANT: Since this counter is used only for information 200 // purposes, it does not use synchronized access. 201 public int activeCount() 202 { 203 return itsObjectCounter; 204 } 205} 206 207// End of file. 208