1. /*
  2. * @(#)BufferManagerWriteCollect.java 1.14 03/12/19
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package com.sun.corba.se.impl.encoding;
  8. import java.nio.ByteBuffer;
  9. import java.util.Iterator;
  10. import java.util.NoSuchElementException;
  11. import java.util.LinkedList;
  12. import com.sun.corba.se.impl.encoding.BufferQueue;
  13. import com.sun.corba.se.impl.encoding.BufferManagerWrite;
  14. import com.sun.corba.se.impl.orbutil.ORBConstants;
  15. import com.sun.corba.se.impl.protocol.giopmsgheaders.Message;
  16. import com.sun.corba.se.impl.encoding.ByteBufferWithInfo;
  17. import com.sun.corba.se.impl.protocol.giopmsgheaders.MessageBase;
  18. import com.sun.corba.se.impl.protocol.giopmsgheaders.FragmentMessage;
  19. import com.sun.corba.se.spi.orb.ORB;
  20. import com.sun.corba.se.impl.encoding.CDROutputObject;
  21. import com.sun.corba.se.impl.orbutil.ORBUtility;
  22. import com.sun.corba.se.pept.transport.Connection;
  23. import com.sun.corba.se.pept.transport.ByteBufferPool;
  24. import com.sun.corba.se.pept.encoding.OutputObject;
  25. /**
  26. * Collect buffer manager.
  27. */
  28. public class BufferManagerWriteCollect extends BufferManagerWrite
  29. {
  30. private BufferQueue queue = new BufferQueue();
  31. private boolean sentFragment = false;
  32. private boolean debug = false;
  33. BufferManagerWriteCollect(ORB orb)
  34. {
  35. super(orb);
  36. if (orb != null)
  37. debug = orb.transportDebugFlag;
  38. }
  39. public boolean sentFragment() {
  40. return sentFragment;
  41. }
  42. /**
  43. * Returns the correct buffer size for this type of
  44. * buffer manager as set in the ORB.
  45. */
  46. public int getBufferSize() {
  47. return orb.getORBData().getGIOPFragmentSize();
  48. }
  49. // Set the fragment's "more fragments" bit to true, put it in the
  50. // queue, and allocate a new bbwi.
  51. public void overflow (ByteBufferWithInfo bbwi)
  52. {
  53. // Set the fragment's moreFragments field to true
  54. MessageBase.setFlag(bbwi.byteBuffer, Message.MORE_FRAGMENTS_BIT);
  55. // Enqueue the previous fragment
  56. queue.enqueue(bbwi);
  57. // Create a new bbwi
  58. ByteBufferWithInfo newBbwi = new ByteBufferWithInfo(orb, this);
  59. newBbwi.fragmented = true;
  60. // XREVISIT - Downcast
  61. ((CDROutputObject)outputObject).setByteBufferWithInfo(newBbwi);
  62. // Now we must marshal in the fragment header/GIOP header
  63. // REVISIT - we can optimize this by not creating the fragment message
  64. // each time.
  65. // XREVISIT - Downcast
  66. FragmentMessage header =
  67. ((CDROutputObject)outputObject).getMessageHeader()
  68. .createFragmentMessage();
  69. header.write((CDROutputObject)outputObject);
  70. }
  71. // Send all fragments
  72. public void sendMessage ()
  73. {
  74. // Enqueue the last fragment
  75. queue.enqueue(((CDROutputObject)outputObject).getByteBufferWithInfo());
  76. Iterator bufs = iterator();
  77. Connection conn =
  78. ((OutputObject)outputObject).getMessageMediator().
  79. getConnection();
  80. // With the collect strategy, we must lock the connection
  81. // while fragments are being sent. This is so that there are
  82. // no interleved fragments in GIOP 1.1.
  83. //
  84. // Note that this thread must not call writeLock again in any
  85. // of its send methods!
  86. conn.writeLock();
  87. try {
  88. // Get a reference to ByteBufferPool so that the ByteBufferWithInfo
  89. // ByteBuffer can be released to the ByteBufferPool
  90. ByteBufferPool byteBufferPool = orb.getByteBufferPool();
  91. while (bufs.hasNext()) {
  92. ByteBufferWithInfo bbwi = (ByteBufferWithInfo)bufs.next();
  93. ((CDROutputObject)outputObject).setByteBufferWithInfo(bbwi);
  94. conn.sendWithoutLock(((CDROutputObject)outputObject));
  95. sentFragment = true;
  96. // Release ByteBufferWithInfo's ByteBuffer back to the pool
  97. // of ByteBuffers.
  98. if (debug)
  99. {
  100. // print address of ByteBuffer being released
  101. int bbAddress = System.identityHashCode(bbwi.byteBuffer);
  102. StringBuffer sb = new StringBuffer(80);
  103. sb.append("sendMessage() - releasing ByteBuffer id (");
  104. sb.append(bbAddress).append(") to ByteBufferPool.");
  105. String msg = sb.toString();
  106. dprint(msg);
  107. }
  108. byteBufferPool.releaseByteBuffer(bbwi.byteBuffer);
  109. bbwi.byteBuffer = null;
  110. bbwi = null;
  111. }
  112. sentFullMessage = true;
  113. } finally {
  114. conn.writeUnlock();
  115. }
  116. }
  117. /**
  118. * Close the BufferManagerWrite - do any outstanding cleanup.
  119. *
  120. * For a BufferManagerWriteGrow any queued ByteBufferWithInfo must
  121. * have its ByteBuffer released to the ByteBufferPool.
  122. */
  123. public void close()
  124. {
  125. // iterate thru queue and release any ByteBufferWithInfo's
  126. // ByteBuffer that may be remaining on the queue to the
  127. // ByteBufferPool.
  128. Iterator bufs = iterator();
  129. ByteBufferPool byteBufferPool = orb.getByteBufferPool();
  130. while (bufs.hasNext())
  131. {
  132. ByteBufferWithInfo bbwi = (ByteBufferWithInfo)bufs.next();
  133. if (bbwi != null && bbwi.byteBuffer != null)
  134. {
  135. if (debug)
  136. {
  137. // print address of ByteBuffer being released
  138. int bbAddress = System.identityHashCode(bbwi.byteBuffer);
  139. StringBuffer sb = new StringBuffer(80);
  140. sb.append("close() - releasing ByteBuffer id (");
  141. sb.append(bbAddress).append(") to ByteBufferPool.");
  142. String msg = sb.toString();
  143. dprint(msg);
  144. }
  145. byteBufferPool.releaseByteBuffer(bbwi.byteBuffer);
  146. bbwi.byteBuffer = null;
  147. bbwi = null;
  148. }
  149. }
  150. }
  151. private void dprint(String msg)
  152. {
  153. ORBUtility.dprint("BufferManagerWriteCollect", msg);
  154. }
  155. private Iterator iterator ()
  156. {
  157. return new BufferManagerWriteCollectIterator();
  158. }
  159. private class BufferManagerWriteCollectIterator implements Iterator
  160. {
  161. public boolean hasNext ()
  162. {
  163. return queue.size() != 0;
  164. }
  165. public Object next ()
  166. {
  167. return queue.dequeue();
  168. }
  169. public void remove ()
  170. {
  171. throw new UnsupportedOperationException();
  172. }
  173. }
  174. }