PG_Stream.java
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:9k
源码类别:

数据库系统

开发平台:

Unix_Linux

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