~ubuntu-branches/ubuntu/wily/libpgjava/wily

« back to all changes in this revision

Viewing changes to src/interfaces/jdbc/org/postgresql/PG_Stream.java

  • Committer: Bazaar Package Importer
  • Author(s): Stefan Gybas
  • Date: 2002-02-06 23:43:06 UTC
  • Revision ID: james.westby@ubuntu.com-20020206234306-hsg7suqr8q56qg40
Tags: upstream-7.2
ImportĀ upstreamĀ versionĀ 7.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package org.postgresql;
 
2
 
 
3
import java.io.*;
 
4
import java.lang.*;
 
5
import java.net.*;
 
6
import java.util.*;
 
7
import java.sql.*;
 
8
import org.postgresql.*;
 
9
import org.postgresql.core.*;
 
10
import org.postgresql.util.*;
 
11
 
 
12
/*
 
13
 * $Id: PG_Stream.java,v 1.16 2001/11/19 23:16:45 momjian Exp $
 
14
 *
 
15
 * This class is used by Connection & PGlobj for communicating with the
 
16
 * backend.
 
17
 *
 
18
 * @see java.sql.Connection
 
19
 */
 
20
//      This class handles all the Streamed I/O for a org.postgresql connection
 
21
public class PG_Stream
 
22
{
 
23
        private Socket connection;
 
24
        private InputStream pg_input;
 
25
        private BufferedOutputStream pg_output;
 
26
        private byte[] byte_buf = new byte[8*1024];
 
27
 
 
28
        BytePoolDim1 bytePoolDim1 = new BytePoolDim1();
 
29
        BytePoolDim2 bytePoolDim2 = new BytePoolDim2();
 
30
 
 
31
        /*
 
32
         * Constructor:  Connect to the PostgreSQL back end and return
 
33
         * a stream connection.
 
34
         *
 
35
         * @param host the hostname to connect to
 
36
         * @param port the port number that the postmaster is sitting on
 
37
         * @exception IOException if an IOException occurs below it.
 
38
         */
 
39
        public PG_Stream(String host, int port) throws IOException
 
40
        {
 
41
                connection = new Socket(host, port);
 
42
 
 
43
                // Submitted by Jason Venner <jason@idiom.com> adds a 10x speed
 
44
                // improvement on FreeBSD machines (caused by a bug in their TCP Stack)
 
45
                connection.setTcpNoDelay(true);
 
46
 
 
47
                // Buffer sizes submitted by Sverre H Huseby <sverrehu@online.no>
 
48
                pg_input = new BufferedInputStream(connection.getInputStream(), 8192);
 
49
                pg_output = new BufferedOutputStream(connection.getOutputStream(), 8192);
 
50
        }
 
51
 
 
52
        /*
 
53
         * Sends a single character to the back end
 
54
         *
 
55
         * @param val the character to be sent
 
56
         * @exception IOException if an I/O error occurs
 
57
         */
 
58
        public void SendChar(int val) throws IOException
 
59
        {
 
60
                pg_output.write((byte)val);
 
61
        }
 
62
 
 
63
        /*
 
64
         * Sends an integer to the back end
 
65
         *
 
66
         * @param val the integer to be sent
 
67
         * @param siz the length of the integer in bytes (size of structure)
 
68
         * @exception IOException if an I/O error occurs
 
69
         */
 
70
        public void SendInteger(int val, int siz) throws IOException
 
71
        {
 
72
                byte[] buf = bytePoolDim1.allocByte(siz);
 
73
 
 
74
                while (siz-- > 0)
 
75
                {
 
76
                        buf[siz] = (byte)(val & 0xff);
 
77
                        val >>= 8;
 
78
                }
 
79
                Send(buf);
 
80
        }
 
81
 
 
82
        /*
 
83
         * Send an array of bytes to the backend
 
84
         *
 
85
         * @param buf The array of bytes to be sent
 
86
         * @exception IOException if an I/O error occurs
 
87
         */
 
88
        public void Send(byte buf[]) throws IOException
 
89
        {
 
90
                pg_output.write(buf);
 
91
        }
 
92
 
 
93
        /*
 
94
         * Send an exact array of bytes to the backend - if the length
 
95
         * has not been reached, send nulls until it has.
 
96
         *
 
97
         * @param buf the array of bytes to be sent
 
98
         * @param siz the number of bytes to be sent
 
99
         * @exception IOException if an I/O error occurs
 
100
         */
 
101
        public void Send(byte buf[], int siz) throws IOException
 
102
        {
 
103
                Send(buf, 0, siz);
 
104
        }
 
105
 
 
106
        /*
 
107
         * Send an exact array of bytes to the backend - if the length
 
108
         * has not been reached, send nulls until it has.
 
109
         *
 
110
         * @param buf the array of bytes to be sent
 
111
         * @param off offset in the array to start sending from
 
112
         * @param siz the number of bytes to be sent
 
113
         * @exception IOException if an I/O error occurs
 
114
         */
 
115
        public void Send(byte buf[], int off, int siz) throws IOException
 
116
        {
 
117
                int i;
 
118
 
 
119
                pg_output.write(buf, off, ((buf.length - off) < siz ? (buf.length - off) : siz));
 
120
                if ((buf.length - off) < siz)
 
121
                {
 
122
                        for (i = buf.length - off ; i < siz ; ++i)
 
123
                        {
 
124
                                pg_output.write(0);
 
125
                        }
 
126
                }
 
127
        }
 
128
 
 
129
        /*
 
130
         * Receives a single character from the backend
 
131
         *
 
132
         * @return the character received
 
133
         * @exception SQLException if an I/O Error returns
 
134
         */
 
135
        public int ReceiveChar() throws SQLException
 
136
        {
 
137
                int c = 0;
 
138
 
 
139
                try
 
140
                {
 
141
                        c = pg_input.read();
 
142
                        if (c < 0)
 
143
                                throw new PSQLException("postgresql.stream.eof");
 
144
                }
 
145
                catch (IOException e)
 
146
                {
 
147
                        throw new PSQLException("postgresql.stream.ioerror", e);
 
148
                }
 
149
                return c;
 
150
        }
 
151
 
 
152
        /*
 
153
         * Receives an integer from the backend
 
154
         *
 
155
         * @param siz length of the integer in bytes
 
156
         * @return the integer received from the backend
 
157
         * @exception SQLException if an I/O error occurs
 
158
         */
 
159
        public int ReceiveInteger(int siz) throws SQLException
 
160
        {
 
161
                int n = 0;
 
162
 
 
163
                try
 
164
                {
 
165
                        for (int i = 0 ; i < siz ; i++)
 
166
                        {
 
167
                                int b = pg_input.read();
 
168
 
 
169
                                if (b < 0)
 
170
                                        throw new PSQLException("postgresql.stream.eof");
 
171
                                n = n | (b << (8 * i)) ;
 
172
                        }
 
173
                }
 
174
                catch (IOException e)
 
175
                {
 
176
                        throw new PSQLException("postgresql.stream.ioerror", e);
 
177
                }
 
178
                return n;
 
179
        }
 
180
 
 
181
        /*
 
182
         * Receives an integer from the backend
 
183
         *
 
184
         * @param siz length of the integer in bytes
 
185
         * @return the integer received from the backend
 
186
         * @exception SQLException if an I/O error occurs
 
187
         */
 
188
        public int ReceiveIntegerR(int siz) throws SQLException
 
189
        {
 
190
                int n = 0;
 
191
 
 
192
                try
 
193
                {
 
194
                        for (int i = 0 ; i < siz ; i++)
 
195
                        {
 
196
                                int b = pg_input.read();
 
197
 
 
198
                                if (b < 0)
 
199
                                        throw new PSQLException("postgresql.stream.eof");
 
200
                                n = b | (n << 8);
 
201
                        }
 
202
                }
 
203
                catch (IOException e)
 
204
                {
 
205
                        throw new PSQLException("postgresql.stream.ioerror", e);
 
206
                }
 
207
                return n;
 
208
        }
 
209
 
 
210
        /*
 
211
         * Receives a null-terminated string from the backend.  If we don't see a
 
212
         * null, then we assume something has gone wrong.
 
213
         *
 
214
         * @param encoding the charset encoding to use.
 
215
         * @return string from back end
 
216
         * @exception SQLException if an I/O error occurs, or end of file
 
217
         */
 
218
        public String ReceiveString(Encoding encoding)
 
219
        throws SQLException
 
220
        {
 
221
                int s = 0;
 
222
                byte[] rst = byte_buf;
 
223
                try
 
224
                {
 
225
                        int buflen = rst.length;
 
226
                        boolean done = false;
 
227
                        while (!done)
 
228
                        {
 
229
                                while (s < buflen)
 
230
                                {
 
231
                                        int c = pg_input.read();
 
232
                                        if (c < 0)
 
233
                                                throw new PSQLException("postgresql.stream.eof");
 
234
                                        else if (c == 0)
 
235
                                        {
 
236
                                                rst[s] = 0;
 
237
                                                done = true;
 
238
                                                break;
 
239
                                        }
 
240
                                        else
 
241
                                        {
 
242
                                                rst[s++] = (byte)c;
 
243
                                        }
 
244
                                        if (s >= buflen)
 
245
                                        { // Grow the buffer
 
246
                                                buflen = (int)(buflen * 2); // 100% bigger
 
247
                                                byte[] newrst = new byte[buflen];
 
248
                                                System.arraycopy(rst, 0, newrst, 0, s);
 
249
                                                rst = newrst;
 
250
                                        }
 
251
                                }
 
252
                        }
 
253
                }
 
254
                catch (IOException e)
 
255
                {
 
256
                        throw new PSQLException("postgresql.stream.ioerror", e);
 
257
                }
 
258
                return encoding.decode(rst, 0, s);
 
259
        }
 
260
 
 
261
        /*
 
262
         * Read a tuple from the back end.      A tuple is a two dimensional
 
263
         * array of bytes
 
264
         *
 
265
         * @param nf the number of fields expected
 
266
         * @param bin true if the tuple is a binary tuple
 
267
         * @return null if the current response has no more tuples, otherwise
 
268
         *      an array of strings
 
269
         * @exception SQLException if a data I/O error occurs
 
270
         */
 
271
        public byte[][] ReceiveTuple(int nf, boolean bin) throws SQLException
 
272
        {
 
273
                int i, bim = (nf + 7) / 8;
 
274
                byte[] bitmask = Receive(bim);
 
275
                byte[][] answer = bytePoolDim2.allocByte(nf);
 
276
 
 
277
                int whichbit = 0x80;
 
278
                int whichbyte = 0;
 
279
 
 
280
                for (i = 0 ; i < nf ; ++i)
 
281
                {
 
282
                        boolean isNull = ((bitmask[whichbyte] & whichbit) == 0);
 
283
                        whichbit >>= 1;
 
284
                        if (whichbit == 0)
 
285
                        {
 
286
                                ++whichbyte;
 
287
                                whichbit = 0x80;
 
288
                        }
 
289
                        if (isNull)
 
290
                                answer[i] = null;
 
291
                        else
 
292
                        {
 
293
                                int len = ReceiveIntegerR(4);
 
294
                                if (!bin)
 
295
                                        len -= 4;
 
296
                                if (len < 0)
 
297
                                        len = 0;
 
298
                                answer[i] = Receive(len);
 
299
                        }
 
300
                }
 
301
                return answer;
 
302
        }
 
303
 
 
304
        /*
 
305
         * Reads in a given number of bytes from the backend
 
306
         *
 
307
         * @param siz number of bytes to read
 
308
         * @return array of bytes received
 
309
         * @exception SQLException if a data I/O error occurs
 
310
         */
 
311
        private byte[] Receive(int siz) throws SQLException
 
312
        {
 
313
                byte[] answer = bytePoolDim1.allocByte(siz);
 
314
                Receive(answer, 0, siz);
 
315
                return answer;
 
316
        }
 
317
 
 
318
        /*
 
319
         * Reads in a given number of bytes from the backend
 
320
         *
 
321
         * @param buf buffer to store result
 
322
         * @param off offset in buffer
 
323
         * @param siz number of bytes to read
 
324
         * @exception SQLException if a data I/O error occurs
 
325
         */
 
326
        public void Receive(byte[] b, int off, int siz) throws SQLException
 
327
        {
 
328
                int s = 0;
 
329
 
 
330
                try
 
331
                {
 
332
                        while (s < siz)
 
333
                        {
 
334
                                int w = pg_input.read(b, off + s, siz - s);
 
335
                                if (w < 0)
 
336
                                        throw new PSQLException("postgresql.stream.eof");
 
337
                                s += w;
 
338
                        }
 
339
                }
 
340
                catch (IOException e)
 
341
                {
 
342
                        throw new PSQLException("postgresql.stream.ioerror", e);
 
343
                }
 
344
        }
 
345
 
 
346
        /*
 
347
         * This flushes any pending output to the backend. It is used primarily
 
348
         * by the Fastpath code.
 
349
         * @exception SQLException if an I/O error occurs
 
350
         */
 
351
        public void flush() throws SQLException
 
352
        {
 
353
                try
 
354
                {
 
355
                        pg_output.flush();
 
356
                }
 
357
                catch (IOException e)
 
358
                {
 
359
                        throw new PSQLException("postgresql.stream.flush", e);
 
360
                }
 
361
        }
 
362
 
 
363
        /*
 
364
         * Closes the connection
 
365
         *
 
366
         * @exception IOException if a IO Error occurs
 
367
         */
 
368
        public void close() throws IOException
 
369
        {
 
370
                pg_output.close();
 
371
                pg_input.close();
 
372
                connection.close();
 
373
        }
 
374
}