BufferManagerWriteCollect.java revision 608:7e06bf1dcb09
1/*
2 * Copyright (c) 2000, 2003, 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 */
25package com.sun.corba.se.impl.encoding;
26
27import java.nio.ByteBuffer;
28import java.util.Iterator;
29import java.util.NoSuchElementException;
30import java.util.LinkedList;
31
32import com.sun.corba.se.impl.encoding.BufferQueue;
33import com.sun.corba.se.impl.encoding.BufferManagerWrite;
34import com.sun.corba.se.impl.orbutil.ORBConstants;
35import com.sun.corba.se.impl.protocol.giopmsgheaders.Message;
36import com.sun.corba.se.impl.encoding.ByteBufferWithInfo;
37import com.sun.corba.se.impl.protocol.giopmsgheaders.MessageBase;
38import com.sun.corba.se.impl.protocol.giopmsgheaders.FragmentMessage;
39import com.sun.corba.se.spi.orb.ORB;
40import com.sun.corba.se.impl.encoding.CDROutputObject;
41import com.sun.corba.se.impl.orbutil.ORBUtility;
42import com.sun.corba.se.pept.transport.Connection;
43import com.sun.corba.se.pept.transport.ByteBufferPool;
44import com.sun.corba.se.pept.encoding.OutputObject;
45
46/**
47 * Collect buffer manager.
48 */
49public class BufferManagerWriteCollect extends BufferManagerWrite
50{
51    private BufferQueue queue = new BufferQueue();
52
53    private boolean sentFragment = false;
54    private boolean debug = false;
55
56
57    BufferManagerWriteCollect(ORB orb)
58    {
59        super(orb);
60         if (orb != null)
61            debug = orb.transportDebugFlag;
62    }
63
64    public boolean sentFragment() {
65        return sentFragment;
66    }
67
68    /**
69     * Returns the correct buffer size for this type of
70     * buffer manager as set in the ORB.
71     */
72    public int getBufferSize() {
73        return orb.getORBData().getGIOPFragmentSize();
74    }
75
76    // Set the fragment's "more fragments" bit to true, put it in the
77    // queue, and allocate a new bbwi.
78    public void overflow (ByteBufferWithInfo bbwi)
79    {
80        // Set the fragment's moreFragments field to true
81        MessageBase.setFlag(bbwi.byteBuffer, Message.MORE_FRAGMENTS_BIT);
82
83        // Enqueue the previous fragment
84        queue.enqueue(bbwi);
85
86        // Create a new bbwi
87        ByteBufferWithInfo newBbwi = new ByteBufferWithInfo(orb, this);
88        newBbwi.fragmented = true;
89
90        // XREVISIT - Downcast
91        ((CDROutputObject)outputObject).setByteBufferWithInfo(newBbwi);
92
93        // Now we must marshal in the fragment header/GIOP header
94
95        // REVISIT - we can optimize this by not creating the fragment message
96        // each time.
97
98        // XREVISIT - Downcast
99        FragmentMessage header =
100              ((CDROutputObject)outputObject).getMessageHeader()
101                                             .createFragmentMessage();
102
103        header.write((CDROutputObject)outputObject);
104    }
105
106    // Send all fragments
107    public void sendMessage ()
108    {
109        // Enqueue the last fragment
110        queue.enqueue(((CDROutputObject)outputObject).getByteBufferWithInfo());
111
112        Iterator bufs = iterator();
113
114        Connection conn =
115                          ((OutputObject)outputObject).getMessageMediator().
116                                                       getConnection();
117
118        // With the collect strategy, we must lock the connection
119        // while fragments are being sent.  This is so that there are
120        // no interleved fragments in GIOP 1.1.
121        //
122        // Note that this thread must not call writeLock again in any
123        // of its send methods!
124        conn.writeLock();
125
126        try {
127
128            // Get a reference to ByteBufferPool so that the ByteBufferWithInfo
129            // ByteBuffer can be released to the ByteBufferPool
130            ByteBufferPool byteBufferPool = orb.getByteBufferPool();
131
132            while (bufs.hasNext()) {
133
134                ByteBufferWithInfo bbwi = (ByteBufferWithInfo)bufs.next();
135                ((CDROutputObject)outputObject).setByteBufferWithInfo(bbwi);
136
137                conn.sendWithoutLock(((CDROutputObject)outputObject));
138
139                sentFragment = true;
140
141                // Release ByteBufferWithInfo's ByteBuffer back to the pool
142                // of ByteBuffers.
143                if (debug)
144                {
145                    // print address of ByteBuffer being released
146                    int bbAddress = System.identityHashCode(bbwi.byteBuffer);
147                    StringBuffer sb = new StringBuffer(80);
148                    sb.append("sendMessage() - releasing ByteBuffer id (");
149                    sb.append(bbAddress).append(") to ByteBufferPool.");
150                    String msg = sb.toString();
151                    dprint(msg);
152                }
153                byteBufferPool.releaseByteBuffer(bbwi.byteBuffer);
154                bbwi.byteBuffer = null;
155                bbwi = null;
156            }
157
158            sentFullMessage = true;
159
160        } finally {
161
162            conn.writeUnlock();
163        }
164    }
165
166    /**
167     * Close the BufferManagerWrite - do any outstanding cleanup.
168     *
169     * For a BufferManagerWriteGrow any queued ByteBufferWithInfo must
170     * have its ByteBuffer released to the ByteBufferPool.
171     */
172    public void close()
173    {
174        // iterate thru queue and release any ByteBufferWithInfo's
175        // ByteBuffer that may be remaining on the queue to the
176        // ByteBufferPool.
177
178        Iterator bufs = iterator();
179
180        ByteBufferPool byteBufferPool = orb.getByteBufferPool();
181
182        while (bufs.hasNext())
183        {
184            ByteBufferWithInfo bbwi = (ByteBufferWithInfo)bufs.next();
185            if (bbwi != null && bbwi.byteBuffer != null)
186            {
187                if (debug)
188                {
189                    // print address of ByteBuffer being released
190                    int bbAddress = System.identityHashCode(bbwi.byteBuffer);
191                    StringBuffer sb = new StringBuffer(80);
192                    sb.append("close() - releasing ByteBuffer id (");
193                    sb.append(bbAddress).append(") to ByteBufferPool.");
194                    String msg = sb.toString();
195                    dprint(msg);
196                }
197                 byteBufferPool.releaseByteBuffer(bbwi.byteBuffer);
198                 bbwi.byteBuffer = null;
199                 bbwi = null;
200            }
201        }
202    }
203
204    private void dprint(String msg)
205    {
206        ORBUtility.dprint("BufferManagerWriteCollect", msg);
207    }
208
209    private Iterator iterator ()
210    {
211        return new BufferManagerWriteCollectIterator();
212    }
213
214    private class BufferManagerWriteCollectIterator implements Iterator
215    {
216        public boolean hasNext ()
217        {
218            return queue.size() != 0;
219        }
220
221        public Object next ()
222        {
223            return queue.dequeue();
224        }
225
226        public void remove ()
227        {
228            throw new UnsupportedOperationException();
229        }
230    }
231}
232