001: /*
002:
003: Derby - Class org.apache.derby.impl.store.raw.data.MemByteHolder
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to you under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.impl.store.raw.data;
023:
024: import org.apache.derby.iapi.services.sanity.SanityManager;
025:
026: import java.io.IOException;
027: import java.io.InputStream;
028: import java.io.OutputStream;
029: import java.util.Vector;
030:
031: /**
032: A ByteHolder that stores all its bytes in memory.
033: */
034: public class MemByteHolder implements ByteHolder {
035: int bufSize;
036:
037: boolean writing = true;
038:
039: Vector bufV;
040: int curBufVEleAt;
041:
042: byte[] curBuf;
043: int curBufPos;
044:
045: //
046: //We use this to determine when we have reached the end
047: //of the current buffer whild reading. For the last
048: //buffer this may be less than bufSize.
049: int curBufDataBytes;
050:
051: //
052: //We use these to remember the location of the last byte
053: //of data we have stored. The read methods use these to
054: //avoid reading more bytes than we have stored. These
055: //values are set by startReading.
056: int lastBufVEleAt = 0;
057: int lastBufDataBytes = 0;
058:
059: /**
060: Create a new MemByteHolder. Store bytes as a list of buffers
061: of size 'bufSize'.
062: */
063: public MemByteHolder(int bufSize) {
064: this .bufSize = bufSize;
065:
066: this .curBuf = new byte[bufSize];
067: this .curBufPos = 0;
068:
069: this .bufV = new Vector(128);
070: bufV.addElement(curBuf);
071: this .curBufVEleAt = 0;
072: }
073:
074: /**
075: @see ByteHolder#write
076: @exception IOException Thrown on error
077: */
078: public void write(int b) throws IOException {
079: if (SanityManager.DEBUG)
080: SanityManager.ASSERT(writing == true,
081: "Writing should be true 1");
082:
083: if (curBufPos >= curBuf.length)
084: getNextBuffer_w();
085:
086: curBuf[curBufPos++] = (byte) b;
087: }
088:
089: /**
090: @see ByteHolder#write
091: @exception IOException Thrown on error
092: */
093: public void write(byte[] data, int offset, int len)
094: throws IOException {
095: if (SanityManager.DEBUG)
096: SanityManager.ASSERT(writing == true,
097: "Writing should be true 2");
098:
099: while (len > 0) {
100: if (curBufPos >= curBuf.length)
101: getNextBuffer_w();
102:
103: int bytesToCopyThisTime = len;
104: int bytesInCurBuf = curBuf.length - curBufPos;
105:
106: if (bytesToCopyThisTime > bytesInCurBuf)
107: bytesToCopyThisTime = bytesInCurBuf;
108: System.arraycopy(data, offset, curBuf, curBufPos,
109: bytesToCopyThisTime);
110: offset += bytesToCopyThisTime;
111: curBufPos += bytesToCopyThisTime;
112: len -= bytesToCopyThisTime;
113: }
114: }
115:
116: /**
117: @see ByteHolder#write
118: @exception IOException Thrown on error
119: */
120: public long write(InputStream is, long count) throws IOException {
121: long bytesToTransfer = count;
122: int bytesTransferredThisTime = 0;
123:
124: do {
125: if (curBufPos >= curBuf.length)
126: getNextBuffer_w();
127:
128: int bytesToTransferThisTime;
129: int bytesInCurBuf = curBuf.length - curBufPos;
130:
131: if (bytesToTransfer >= bytesInCurBuf)
132: bytesToTransferThisTime = bytesInCurBuf;
133: else
134: bytesToTransferThisTime = (int) bytesToTransfer;
135: //
136: //Note read should never return 0. Thus we keep looping
137: //transferring bytes from the stream to our buffer until
138: //we transfer count bytes or reach the end of the stream.
139: //
140: bytesTransferredThisTime = is.read(curBuf, curBufPos,
141: bytesToTransferThisTime);
142:
143: if (bytesTransferredThisTime > 0) {
144: if (SanityManager.DEBUG)
145: SanityManager.ASSERT(writing == true,
146: "Writing should be true 3");
147:
148: bytesToTransfer -= bytesTransferredThisTime;
149: curBufPos += bytesTransferredThisTime;
150: }
151: } while (bytesToTransfer > 0 && bytesTransferredThisTime > 0);
152:
153: return count - bytesToTransfer;
154: }
155:
156: /**
157: @see ByteHolder#clear
158:
159: @exception IOException Thrown on error
160: */
161: public void clear() throws IOException {
162: writing = true;
163:
164: curBuf = (byte[]) bufV.elementAt(0);
165: this .curBufVEleAt = 0;
166: this .curBufPos = 0;
167:
168: lastBufVEleAt = 0;
169: lastBufDataBytes = 0;
170: }
171:
172: /**
173: @see ByteHolder#startReading
174: */
175: public void startReading() throws IOException {
176: if (writing == true) {
177: //Enter read mode.
178: writing = false;
179: lastBufDataBytes = curBufPos;
180: lastBufVEleAt = curBufVEleAt;
181: }
182: //
183: //Reposition so reads start from the first
184: //byte.
185: curBuf = (byte[]) bufV.elementAt(0);
186: this .curBufVEleAt = 0;
187: this .curBufPos = 0;
188: if (curBufVEleAt == lastBufVEleAt)
189: curBufDataBytes = lastBufDataBytes;
190: else
191: curBufDataBytes = bufSize;
192: }
193:
194: /**
195: @see ByteHolder#read
196: @exception IOException Thrown on error
197: */
198: public int read() throws IOException {
199: if (SanityManager.DEBUG)
200: SanityManager.ASSERT(writing == false,
201: "Reading should be true 2");
202:
203: if (curBufPos >= curBufDataBytes)
204: getNextBuffer_r();
205:
206: if (curBufPos >= curBufDataBytes)
207: return -1;
208: else
209: return 0xff & curBuf[curBufPos++];
210: }
211:
212: /**
213: @see ByteHolder#read
214: @exception IOException Thrown on error
215: */
216: public int read(byte b[], int off, int len) throws IOException {
217: return (read(b, off, (OutputStream) null, len));
218: }
219:
220: /**
221: @see ByteHolder#read
222: @exception IOException Thrown on error
223: */
224: public int read(OutputStream out, int len) throws IOException {
225: return (read((byte[]) null, 0, out, len));
226: }
227:
228: /**
229: @see ByteHolder#read
230: @exception IOException Thrown on error
231: */
232: public int read(byte b[], int off, OutputStream out, int len)
233: throws IOException {
234: int bytesIRead = 0;
235: boolean eof = false;
236:
237: if (SanityManager.DEBUG)
238: SanityManager.ASSERT(writing == false,
239: "Reading should be true 3");
240:
241: if (curBufPos >= curBufDataBytes)
242: eof = getNextBuffer_r();
243:
244: if (eof)
245: return -1;
246:
247: while (len > 0 && !eof) {
248: int bytesInCurBuf = curBufDataBytes - curBufPos;
249: int bytesIReadThisTime;
250: if (len >= bytesInCurBuf)
251: bytesIReadThisTime = bytesInCurBuf;
252: else
253: bytesIReadThisTime = len;
254:
255: if (out == null) {
256: // write the data to the byte array
257: System.arraycopy(curBuf, curBufPos, b, off,
258: bytesIReadThisTime);
259: } else {
260: // write the data to the output stream
261: out.write(curBuf, curBufPos, bytesIReadThisTime);
262: }
263: off += bytesIReadThisTime;
264: curBufPos += bytesIReadThisTime;
265: len -= bytesIReadThisTime;
266: bytesIRead += bytesIReadThisTime;
267: if (curBufPos >= curBufDataBytes)
268: eof = getNextBuffer_r();
269: }
270:
271: return bytesIRead;
272: }
273:
274: /**
275: @see ByteHolder#shiftToFront
276: @exception IOException Thrown on error
277: */
278: public int shiftToFront() throws IOException {
279: int remainingBytes = available();
280: remainingBytes = remainingBytes > 0 ? remainingBytes : (-1)
281: * remainingBytes;
282:
283: byte b[] = new byte[remainingBytes + 1];
284: int bytesRead = read(b, 0, remainingBytes);
285:
286: // clear the buffer
287: clear();
288:
289: // put the bytes at the beginning of the buffer
290: writing = true;
291: write(b, 0, bytesRead);
292:
293: curBufDataBytes = 0;
294:
295: return bytesRead;
296: }
297:
298: /**
299: @see ByteHolder#available
300: */
301: public int available() {
302: //if (SanityManager.DEBUG)
303: // SanityManager.ASSERT(writing == false,
304: // "Reading should be true 3");
305:
306: int curBufAvailable = curBufDataBytes - curBufPos;
307: int lastBufAvailable = 0;
308: int middleBuffers = 0;
309: if (curBufVEleAt != lastBufVEleAt) {
310: middleBuffers = lastBufVEleAt - curBufVEleAt - 1;
311: lastBufAvailable = lastBufDataBytes;
312: }
313: int availableBytes = curBufAvailable + lastBufAvailable
314: + middleBuffers * bufSize;
315:
316: return availableBytes;
317: }
318:
319: /**
320: Return the number of bytes that have been saved to this byte holder.
321: This result is different from available() as it is unaffected by the
322: current read position on the ByteHolder.
323:
324: @see ByteHolder#numBytesSaved
325: */
326: public int numBytesSaved() {
327: int ret_val;
328:
329: if (writing) {
330: // still writing, so use the cur* variables
331: if (SanityManager.DEBUG)
332: SanityManager.ASSERT(lastBufVEleAt == 0
333: && lastBufDataBytes == 0,
334: "counters were somehow bumped during writing");
335:
336: ret_val = (curBufVEleAt * bufSize) + curBufPos;
337: } else {
338: ret_val = (lastBufVEleAt * bufSize) + lastBufDataBytes;
339: }
340:
341: return (ret_val);
342: }
343:
344: /**
345: @see ByteHolder#skip
346: @exception IOException Thrown on error
347: */
348: public long skip(long count) throws IOException {
349: long bytesISkipped = 0;
350: boolean eof = false;
351:
352: if (SanityManager.DEBUG)
353: SanityManager.ASSERT(writing == false,
354: "Reading should be true 4");
355:
356: if (curBufPos >= curBufDataBytes)
357: eof = getNextBuffer_r();
358:
359: while (count > 0 && !eof) {
360: int bytesInCurBuf = curBufDataBytes - curBufPos;
361: int bytesISkippedThisTime;
362:
363: if (count >= bytesInCurBuf)
364: bytesISkippedThisTime = bytesInCurBuf;
365: else
366: bytesISkippedThisTime = (int) count;
367:
368: curBufPos += bytesISkippedThisTime;
369: count -= bytesISkippedThisTime;
370: bytesISkipped += bytesISkippedThisTime;
371:
372: if (count > 0)
373: eof = getNextBuffer_r();
374: }
375:
376: return bytesISkipped;
377: }
378:
379: /**
380: @see ByteHolder#writingMode
381: */
382: public boolean writingMode() {
383: return writing;
384: }
385:
386: /**
387: Get the next buffer for writing bytes.
388: @exception IOException Thrown on error
389: */
390: protected void getNextBuffer_w() throws IOException {
391: if (SanityManager.DEBUG) {
392: getNextBuffer_w_Sanity();
393: }
394:
395: curBufVEleAt++;
396:
397: if (bufV.size() <= curBufVEleAt) {
398: curBuf = new byte[bufSize];
399: bufV.addElement(curBuf);
400: } else {
401: curBuf = (byte[]) bufV.elementAt(curBufVEleAt);
402: }
403:
404: initBuffer_w();
405: }
406:
407: /** Do sanity checking when getting the next write buffer */
408: protected void getNextBuffer_w_Sanity() {
409: if (SanityManager.DEBUG) {
410: SanityManager.ASSERT(curBufPos == curBuf.length,
411: "partial write");
412:
413: SanityManager.ASSERT(writing == true,
414: "Writing should be true 5");
415: }
416: }
417:
418: /** Initialize a buffer for writing */
419: protected void initBuffer_w() {
420: curBufPos = 0;
421:
422: if (SanityManager.DEBUG) {
423: SanityManager.ASSERT(curBuf.length == bufSize,
424: "bad Buf Length " + curBuf.length);
425: }
426: }
427:
428: /**
429: Get the next buffer for reading bytes.
430:
431: @return true if the user has read all the bytes
432: in this ByteHolder.
433:
434: @exception IOException Thrown on error
435: */
436: protected boolean getNextBuffer_r() throws IOException {
437: if (SanityManager.DEBUG)
438: SanityManager.ASSERT(writing == false,
439: "Reading should be true 5");
440: if (curBufVEleAt >= lastBufVEleAt)
441: return true;
442: curBuf = (byte[]) bufV.elementAt(++curBufVEleAt);
443: curBufPos = 0;
444: if (curBufVEleAt == lastBufVEleAt)
445: curBufDataBytes = lastBufDataBytes;
446: else
447: curBufDataBytes = bufSize;
448: return false;
449: }
450:
451: /**
452: Create a string representation of an internal buffer of bytes.
453: This is useful during debugging.
454: */
455: private String dumpBuf(int bufVEleAt) {
456: StringBuffer sb = new StringBuffer(100);
457:
458: byte[] buf = (byte[]) bufV.elementAt(bufVEleAt);
459: sb.append("(");
460: for (int ix = 0; ix < buf.length; ix++)
461: sb.append(buf[ix] + ".");
462: sb.append(")");
463: return sb.toString();
464: }
465:
466: /**
467: Produce a string describing the state of this ByteHolder.
468: This is mainly for debugging.
469: */
470: public String toString() {
471: return " writing: " + writing + " curBufVEleAt: "
472: + curBufVEleAt + " curBufPos: " + curBufPos
473: + " curBufDataBytes: " + curBufDataBytes
474: + " lastBufVEleAt: " + lastBufVEleAt
475: + " lastBufDataBytes: " + lastBufDataBytes
476: + " curBuf: " + dumpBuf(curBufVEleAt);
477: }
478: }
|