ByteBufferWithInfo.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 */
25
26package com.sun.corba.se.impl.encoding;
27
28import java.nio.ByteBuffer;
29
30
31import com.sun.corba.se.impl.encoding.BufferManagerWrite;
32import com.sun.corba.se.impl.orbutil.ORBUtility;
33import com.sun.corba.se.pept.transport.ByteBufferPool;
34import com.sun.corba.se.spi.orb.ORB;
35
36
37// Notes about the class.
38// Assumptions, the ByteBuffer's position is set by the constructor's
39// index variable and the ByteBuffer's limit points to the end of the
40// data. Also, since the index variable tracks the current empty
41// position in the buffer, the ByteBuffer's position is updated
42// any time there's a call to this class's position().
43// Although, a ByteBuffer's length is it's capacity(), the context in
44// which length is used in this object, this.buflen is actually the
45// ByteBuffer limit().
46
47public class ByteBufferWithInfo
48{
49    private ORB orb;
50    private boolean debug;
51    // REVISIT - index should eventually be replaced with byteBuffer.position()
52    private int     index;     // Current empty position in buffer.
53    // REVISIT - CHANGE THESE TO PRIVATE
54    public ByteBuffer byteBuffer;// Marshal buffer.
55    public int     buflen;     // Total length of buffer. // Unnecessary...
56    public int     needed;     // How many more bytes are needed on overflow.
57    public boolean fragmented; // Did the overflow operation fragment?
58
59    public ByteBufferWithInfo(org.omg.CORBA.ORB orb,
60                              ByteBuffer byteBuffer,
61                              int index)
62    {
63        this.orb = (com.sun.corba.se.spi.orb.ORB)orb;
64        debug = this.orb.transportDebugFlag;
65        this.byteBuffer = byteBuffer;
66        if (byteBuffer != null)
67        {
68            this.buflen = byteBuffer.limit();
69        }
70        position(index);
71        this.needed = 0;
72        this.fragmented = false;
73    }
74
75    public ByteBufferWithInfo(org.omg.CORBA.ORB orb, ByteBuffer byteBuffer)
76    {
77        this(orb, byteBuffer, 0);
78    }
79
80    public ByteBufferWithInfo(org.omg.CORBA.ORB orb,
81                              BufferManagerWrite bufferManager)
82    {
83        this(orb, bufferManager, true);
84    }
85
86    // Right now, EncapsOutputStream's do not use pooled byte buffers.
87    // EncapsOutputStream's is the only one that does not use pooled
88    // byte buffers. Hence, the reason for the boolean 'usePooledByteBuffers'.
89    // See EncapsOutputStream for additional information.
90
91    public ByteBufferWithInfo(org.omg.CORBA.ORB orb,
92                              BufferManagerWrite bufferManager,
93                              boolean usePooledByteBuffers)
94    {
95        this.orb = (com.sun.corba.se.spi.orb.ORB)orb;
96        debug = this.orb.transportDebugFlag;
97
98        int bufferSize = bufferManager.getBufferSize();
99
100        if (usePooledByteBuffers)
101        {
102            ByteBufferPool byteBufferPool = this.orb.getByteBufferPool();
103            this.byteBuffer = byteBufferPool.getByteBuffer(bufferSize);
104
105            if (debug)
106            {
107                // print address of ByteBuffer gotten from pool
108                int bbAddress = System.identityHashCode(byteBuffer);
109                StringBuffer sb = new StringBuffer(80);
110                sb.append("constructor (ORB, BufferManagerWrite) - got ")
111                  .append("ByteBuffer id (").append(bbAddress)
112                  .append(") from ByteBufferPool.");
113                String msgStr = sb.toString();
114                dprint(msgStr);
115            }
116        }
117        else
118        {
119             // don't allocate from pool, allocate non-direct ByteBuffer
120             this.byteBuffer = ByteBuffer.allocate(bufferSize);
121        }
122
123        position(0);
124        this.buflen = bufferSize;
125        this.byteBuffer.limit(this.buflen);
126        this.needed = 0;
127        this.fragmented = false;
128    }
129
130    // Shallow copy constructor
131    public ByteBufferWithInfo (ByteBufferWithInfo bbwi)
132    {
133        this.orb = bbwi.orb;
134        this.debug = bbwi.debug;
135        this.byteBuffer = bbwi.byteBuffer;
136        this.buflen = bbwi.buflen;
137        this.byteBuffer.limit(this.buflen);
138        position(bbwi.position());
139        this.needed = bbwi.needed;
140        this.fragmented = bbwi.fragmented;
141    }
142
143    // So IIOPOutputStream seems more intuitive
144    public int getSize()
145    {
146        return position();
147    }
148
149    // accessor to buflen
150    public int getLength()
151    {
152         return buflen;
153    }
154
155    // get position in this buffer
156    public int position()
157    {
158        // REVISIT - This should be changed to return the
159        //           value of byteBuffer.position() rather
160        //           than this.index. But, byteBuffer.position
161        //           is manipulated via ByteBuffer writes, reads,
162        //           gets and puts. These locations need to be
163        //           investigated and updated before
164        //           byteBuffer.position() can be returned here.
165        // return byteBuffer.position();
166        return index;
167    }
168
169    // set position in this buffer
170    public void position(int newPosition)
171    {
172        // REVISIT - This should be changed to set only the
173        //           value of byteBuffer.position rather
174        //           than this.index. This change should be made
175        //           in conjunction with the change to this.position().
176        byteBuffer.position(newPosition);
177        index = newPosition;
178    }
179
180    // mutator to buflen
181    public void setLength(int theLength)
182    {
183        buflen = theLength;
184        byteBuffer.limit(buflen);
185    }
186
187    // Grow byteBuffer to a size larger than position() + needed
188    public void growBuffer(com.sun.corba.se.spi.orb.ORB orb)
189    {
190        // This code used to live directly in CDROutputStream.grow.
191
192        // Recall that the byteBuffer size is 'really' the limit or
193        // buflen.
194
195        int newLength = byteBuffer.limit() * 2;
196
197        while (position() + needed >= newLength)
198            newLength = newLength * 2;
199
200        ByteBufferPool byteBufferPool = orb.getByteBufferPool();
201        ByteBuffer newBB = byteBufferPool.getByteBuffer(newLength);
202
203        if (debug)
204        {
205            // print address of ByteBuffer just gotten
206            int newbbAddress = System.identityHashCode(newBB);
207            StringBuffer sb = new StringBuffer(80);
208            sb.append("growBuffer() - got ByteBuffer id (");
209            sb.append(newbbAddress).append(") from ByteBufferPool.");
210            String msgStr = sb.toString();
211            dprint(msgStr);
212        }
213
214        byteBuffer.position(0);
215        newBB.put(byteBuffer);
216
217        // return 'old' byteBuffer reference to the ByteBuffer pool
218        if (debug)
219        {
220            // print address of ByteBuffer being released
221            int bbAddress = System.identityHashCode(byteBuffer);
222            StringBuffer sb = new StringBuffer(80);
223            sb.append("growBuffer() - releasing ByteBuffer id (");
224            sb.append(bbAddress).append(") to ByteBufferPool.");
225            String msgStr2 = sb.toString();
226            dprint(msgStr2);
227        }
228        byteBufferPool.releaseByteBuffer(byteBuffer);
229
230        // update the byteBuffer with a larger ByteBuffer
231        byteBuffer = newBB;
232
233        // limit and buflen must be set to newLength.
234        buflen = newLength;
235        byteBuffer.limit(buflen);
236    }
237
238    public String toString()
239    {
240        StringBuffer str = new StringBuffer("ByteBufferWithInfo:");
241
242        str.append(" buflen = " + buflen);
243        str.append(" byteBuffer.limit = " + byteBuffer.limit());
244        str.append(" index = " + index);
245        str.append(" position = " + position());
246        str.append(" needed = " + needed);
247        str.append(" byteBuffer = " + (byteBuffer == null ? "null" : "not null"));
248        str.append(" fragmented = " + fragmented);
249
250        return str.toString();
251    }
252
253    protected void dprint(String msg)
254    {
255        ORBUtility.dprint("ByteBufferWithInfo", msg);
256    }
257}
258