EMMA Coverage Report (generated Tue Jul 25 14:15:05 CDT 2006)
[all classes][com.mysql.jdbc.util]

COVERAGE SUMMARY FOR SOURCE FILE [ReadAheadInputStream.java]

nameclass, %method, %block, %line, %
ReadAheadInputStream.java100% (1/1)73%  (8/11)82%  (395/482)83%  (97.6/118)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ReadAheadInputStream100% (1/1)73%  (8/11)82%  (395/482)83%  (97.6/118)
ReadAheadInputStream (InputStream, boolean, Log): void 0%   (0/1)0%   (0/7)0%   (0/2)
markSupported (): boolean 0%   (0/1)0%   (0/2)0%   (0/1)
read (): int 0%   (0/1)0%   (0/30)0%   (0/6)
checkClosed (): void 100% (1/1)44%  (4/9)67%  (2/3)
skip (long): long 100% (1/1)61%  (33/54)57%  (6.9/12)
close (): void 100% (1/1)83%  (20/24)97%  (7.7/8)
read (byte [], int, int): int 100% (1/1)90%  (54/60)88%  (14/16)
readFromUnderlyingStreamIfNecessary (byte [], int, int): int 100% (1/1)93%  (113/121)93%  (27/29)
fill (int): void 100% (1/1)97%  (140/144)97%  (31/32)
ReadAheadInputStream (InputStream, int, boolean, Log): void 100% (1/1)100% (19/19)100% (7/7)
available (): int 100% (1/1)100% (12/12)100% (2/2)

1/*
2 Copyright (C) 2002-2005 MySQL AB
3 
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of version 2 of the GNU General Public License as
6 published by the Free Software Foundation.
7 
8 There are special exceptions to the terms and conditions of the GPL
9 as it is applied to this software. View the full text of the
10 exception in file EXCEPTIONS-CONNECTOR-J in the directory of this
11 software distribution.
12 
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21 
22 
23 */
24 
25package com.mysql.jdbc.util;
26 
27import java.io.IOException;
28import java.io.InputStream;
29 
30import com.mysql.jdbc.log.Log;
31 
32/**
33 * A non-blocking buffered input stream. Reads more if it can, won't block to
34 * fill the buffer, only blocks to satisfy a request of read(byte[])
35 * 
36 * @author Mark Matthews
37 * 
38 * @version $Id: ReadAheadInputStream.java,v 1.1.2.1 2005/05/13 18:58:39
39 *          mmatthews Exp $
40 */
41public class ReadAheadInputStream extends InputStream {
42 
43        private final static int DEFAULT_BUFFER_SIZE = 4096;
44 
45        private InputStream underlyingStream;
46 
47        private byte buf[];
48 
49        protected int endOfCurrentData;
50 
51        protected int currentPosition;
52 
53        protected boolean doDebug = false;
54        
55        protected Log log;
56 
57        private void fill(int readAtLeastTheseManyBytes) throws IOException {
58                checkClosed();
59 
60                this.currentPosition = 0; /* no mark: throw away the buffer */
61 
62                this.endOfCurrentData = currentPosition;
63 
64                // Read at least as many bytes as the caller wants, but don't
65                // block to fill the whole buffer (like java.io.BufferdInputStream
66                // does)
67 
68                int bytesToRead = Math.min(this.buf.length - currentPosition,
69                                readAtLeastTheseManyBytes);
70 
71                int bytesAvailable = this.underlyingStream.available();
72 
73                if (bytesAvailable > bytesToRead) {
74 
75                        // Great, there's more available, let's grab those
76                        // bytes too! (read-ahead)
77 
78                        bytesToRead = Math.min(this.buf.length - currentPosition,
79                                        bytesAvailable);
80                }
81 
82                if (this.doDebug) {
83                        StringBuffer debugBuf = new StringBuffer();
84                        debugBuf.append("  ReadAheadInputStream.fill(");
85                        debugBuf.append(readAtLeastTheseManyBytes);
86                        debugBuf.append("), buffer_size=");
87                        debugBuf.append(this.buf.length);
88                        debugBuf.append(", current_position=");
89                        debugBuf.append(currentPosition);
90                        debugBuf.append(", need to read ");
91                        debugBuf.append(Math.min(this.buf.length - currentPosition,
92                                        readAtLeastTheseManyBytes));
93                        debugBuf.append(" bytes to fill request,");
94 
95                        if (bytesAvailable > 0) {
96                                debugBuf.append(" underlying InputStream reports ");
97                                debugBuf.append(bytesAvailable);
98 
99                                debugBuf.append(" total bytes available,");
100                        }
101 
102                        debugBuf.append(" attempting to read ");
103                        debugBuf.append(bytesToRead);
104                        debugBuf.append(" bytes.");
105 
106                        if (this.log != null) {
107                                this.log.logTrace(debugBuf.toString());
108                        } else {
109                                System.err.println(debugBuf.toString());
110                        }
111                }
112 
113                int n = this.underlyingStream.read(this.buf, currentPosition,
114                                bytesToRead);
115 
116                if (n > 0) {
117                        endOfCurrentData = n + currentPosition;
118                }
119        }
120 
121        private int readFromUnderlyingStreamIfNecessary(byte[] b, int off, int len)
122                        throws IOException {
123                checkClosed();
124 
125                int avail = endOfCurrentData - currentPosition;
126 
127                if (this.doDebug) {
128                        StringBuffer debugBuf = new StringBuffer();
129                        debugBuf.append("ReadAheadInputStream.readIfNecessary(");
130                        debugBuf.append(b);
131                        debugBuf.append(",");
132                        debugBuf.append(off);
133                        debugBuf.append(",");
134                        debugBuf.append(len);
135                        debugBuf.append(")");
136 
137                        if (avail <= 0) {
138                                debugBuf
139                                                .append(" not all data available in buffer, must read from stream");
140 
141                                if (len >= this.buf.length) {
142                                        debugBuf
143                                                        .append(", amount requested > buffer, returning direct read() from stream");
144                                }
145                        }
146 
147                        if (this.log != null) {
148                                this.log.logTrace(debugBuf.toString());
149                        } else {
150                                System.err.println(debugBuf.toString());
151                        }
152                }
153 
154                if (avail <= 0) {
155 
156                        if (len >= this.buf.length) {
157                                return this.underlyingStream.read(b, off, len);
158                        }
159 
160                        fill(len);
161 
162                        avail = endOfCurrentData - currentPosition;
163 
164                        if (avail <= 0)
165                                return -1;
166                }
167 
168                int bytesActuallyRead = (avail < len) ? avail : len;
169 
170                System.arraycopy(this.buf, currentPosition, b, off, bytesActuallyRead);
171 
172                this.currentPosition += bytesActuallyRead;
173 
174                return bytesActuallyRead;
175        }
176 
177        public synchronized int read(byte b[], int off, int len) throws IOException {
178                checkClosed(); // Check for closed stream
179                if ((off | len | (off + len) | (b.length - (off + len))) < 0) {
180                        throw new IndexOutOfBoundsException();
181                } else if (len == 0) {
182                        return 0;
183                }
184 
185                int totalBytesRead = 0;
186 
187                while (true) {
188                        int bytesReadThisRound = readFromUnderlyingStreamIfNecessary(b, off
189                                        + totalBytesRead, len - totalBytesRead);
190 
191                        // end-of-stream?
192                        if (bytesReadThisRound <= 0) {
193                                if (totalBytesRead == 0) {
194                                        totalBytesRead = bytesReadThisRound;
195                                }
196 
197                                break;
198                        }
199 
200                        totalBytesRead += bytesReadThisRound;
201 
202                        // Read _at_least_ enough bytes
203                        if (totalBytesRead >= len) {
204                                break;
205                        }
206 
207                        // Nothing to read?
208                        if (this.underlyingStream.available() <= 0) {
209                                break;
210                        }
211                }
212 
213                return totalBytesRead;
214        }
215 
216        public int read() throws IOException {
217                checkClosed();
218 
219                if (currentPosition >= endOfCurrentData) {
220                        fill(1);
221                        if (currentPosition >= endOfCurrentData)
222                                return -1;
223                }
224 
225                return this.buf[currentPosition++] & 0xff;
226        }
227 
228        public int available() throws IOException {
229                checkClosed();
230 
231                return this.underlyingStream.available()
232                                + (this.endOfCurrentData - this.currentPosition);
233        }
234 
235        private void checkClosed() throws IOException {
236 
237                if (this.buf == null) {
238                        throw new IOException("Stream closed");
239                }
240        }
241 
242        /**
243         * 
244         */
245        public ReadAheadInputStream(InputStream toBuffer, boolean debug, Log logTo) {
246                this(toBuffer, DEFAULT_BUFFER_SIZE, debug, logTo);
247        }
248 
249        public ReadAheadInputStream(InputStream toBuffer, int bufferSize,
250                        boolean debug,
251                        Log logTo) {
252                this.underlyingStream = toBuffer;
253                this.buf = new byte[bufferSize];
254                this.doDebug = debug;
255                this.log = logTo;
256        }
257 
258        /*
259         * (non-Javadoc)
260         * 
261         * @see java.io.Closeable#close()
262         */
263        public void close() throws IOException {
264                if (this.underlyingStream != null) {
265                        try {
266                                this.underlyingStream.close();
267                        } finally {
268                                this.underlyingStream = null;
269                                this.buf = null;
270                                this.log = null;
271                        }
272                }
273        }
274 
275        /*
276         * (non-Javadoc)
277         * 
278         * @see java.io.InputStream#markSupported()
279         */
280        public boolean markSupported() {
281                return false;
282        }
283 
284        /*
285         * (non-Javadoc)
286         * 
287         * @see java.io.InputStream#skip(long)
288         */
289        public long skip(long n) throws IOException {
290                checkClosed();
291                if (n <= 0) {
292                        return 0;
293                }
294 
295                long bytesAvailInBuffer = this.endOfCurrentData - this.currentPosition;
296 
297                if (bytesAvailInBuffer <= 0) {
298 
299                        fill((int) n);
300                        bytesAvailInBuffer = this.endOfCurrentData - this.currentPosition;
301                        if (bytesAvailInBuffer <= 0)
302                                return 0;
303                }
304 
305                long bytesSkipped = (bytesAvailInBuffer < n) ? bytesAvailInBuffer : n;
306                this.currentPosition += bytesSkipped;
307                return bytesSkipped;
308        }
309}

[all classes][com.mysql.jdbc.util]
EMMA 2.0.4217 (C) Vladimir Roubtsov