summaryrefslogtreecommitdiff
path: root/src/interfaces/jdbc/org/postgresql/PG_Stream.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/interfaces/jdbc/org/postgresql/PG_Stream.java')
-rw-r--r--src/interfaces/jdbc/org/postgresql/PG_Stream.java206
1 files changed, 194 insertions, 12 deletions
diff --git a/src/interfaces/jdbc/org/postgresql/PG_Stream.java b/src/interfaces/jdbc/org/postgresql/PG_Stream.java
index 22c41bdb3a..9a2b712dda 100644
--- a/src/interfaces/jdbc/org/postgresql/PG_Stream.java
+++ b/src/interfaces/jdbc/org/postgresql/PG_Stream.java
@@ -23,6 +23,9 @@ public class PG_Stream
private InputStream pg_input;
private BufferedOutputStream pg_output;
+ BytePoolDim1 bytePoolDim1 = new BytePoolDim1();
+ BytePoolDim2 bytePoolDim2 = new BytePoolDim2();
+
/**
* Constructor: Connect to the PostgreSQL back end and return
* a stream connection.
@@ -70,7 +73,7 @@ public class PG_Stream
*/
public void SendInteger(int val, int siz) throws IOException
{
- byte[] buf = new byte[siz];
+ byte[] buf = bytePoolDim1.allocByte(siz);
while (siz-- > 0)
{
@@ -94,7 +97,7 @@ public class PG_Stream
*/
public void SendIntegerReverse(int val, int siz) throws IOException
{
- byte[] buf = new byte[siz];
+ byte[] buf = bytePoolDim1.allocByte(siz);
int p=0;
while (siz-- > 0)
{
@@ -236,15 +239,27 @@ public class PG_Stream
return n;
}
- public String ReceiveString(int maxsize) throws SQLException {
- return ReceiveString(maxsize, null);
- }
-
/**
* Receives a null-terminated string from the backend. Maximum of
* maxsiz bytes - if we don't see a null, then we assume something
* has gone wrong.
*
+ * @param maxsiz maximum length of string
+ * @return string from back end
+ * @exception SQLException if an I/O error occurs
+ */
+ public String ReceiveString(int maxsiz) throws SQLException
+ {
+ byte[] rst = bytePoolDim1.allocByte(maxsiz);
+ return ReceiveString(rst, maxsiz, null);
+ }
+
+ /**
+ * Receives a null-terminated string from the backend. Maximum of
+ * maxsiz bytes - if we don't see a null, then we assume something
+ * has gone wrong.
+ *
+ * @param maxsiz maximum length of string
* @param encoding the charset encoding to use.
* @param maxsiz maximum length of string in bytes
* @return string from back end
@@ -252,7 +267,25 @@ public class PG_Stream
*/
public String ReceiveString(int maxsiz, String encoding) throws SQLException
{
- byte[] rst = new byte[maxsiz];
+ byte[] rst = bytePoolDim1.allocByte(maxsiz);
+ return ReceiveString(rst, maxsiz, encoding);
+ }
+
+ /**
+ * Receives a null-terminated string from the backend. Maximum of
+ * maxsiz bytes - if we don't see a null, then we assume something
+ * has gone wrong.
+ *
+ * @param rst byte array to read the String into. rst.length must
+ * equal to or greater than maxsize.
+ * @param maxsiz maximum length of string in bytes
+ * @param encoding the charset encoding to use.
+ * @return string from back end
+ * @exception SQLException if an I/O error occurs
+ */
+ public String ReceiveString(byte rst[], int maxsiz, String encoding)
+ throws SQLException
+ {
int s = 0;
try
@@ -262,9 +295,10 @@ public class PG_Stream
int c = pg_input.read();
if (c < 0)
throw new PSQLException("postgresql.stream.eof");
- else if (c == 0)
- break;
- else
+ else if (c == 0) {
+ rst[s] = 0;
+ break;
+ } else
rst[s++] = (byte)c;
}
if (s >= maxsiz)
@@ -299,7 +333,7 @@ public class PG_Stream
{
int i, bim = (nf + 7)/8;
byte[] bitmask = Receive(bim);
- byte[][] answer = new byte[nf][0];
+ byte[][] answer = bytePoolDim2.allocByte(nf);
int whichbit = 0x80;
int whichbyte = 0;
@@ -337,7 +371,7 @@ public class PG_Stream
*/
private byte[] Receive(int siz) throws SQLException
{
- byte[] answer = new byte[siz];
+ byte[] answer = bytePoolDim1.allocByte(siz);
Receive(answer,0,siz);
return answer;
}
@@ -395,4 +429,152 @@ public class PG_Stream
pg_input.close();
connection.close();
}
+
+ /**
+ * Deallocate all resources that has been associated with any previous
+ * query.
+ */
+ public void deallocate(){
+ bytePoolDim1.deallocate();
+ bytePoolDim2.deallocate();
+ }
+}
+
+/**
+ * A simple and fast object pool implementation that can pool objects
+ * of any type. This implementation is not thread safe, it is up to the users
+ * of this class to assure thread safety.
+ */
+class ObjectPool {
+ int cursize = 0;
+ int maxsize = 16;
+ Object arr[] = new Object[maxsize];
+
+ public void add(Object o){
+ if(cursize >= maxsize){
+ Object newarr[] = new Object[maxsize*2];
+ System.arraycopy(arr, 0, newarr, 0, maxsize);
+ maxsize = maxsize * 2;
+ arr = newarr;
+ }
+ arr[cursize++] = o;
+ }
+
+ public Object remove(){
+ return arr[--cursize];
+ }
+ public boolean isEmpty(){
+ return cursize == 0;
+ }
+ public int size(){
+ return cursize;
+ }
+ public void addAll(ObjectPool pool){
+ int srcsize = pool.size();
+ if(srcsize == 0)
+ return;
+ int totalsize = srcsize + cursize;
+ if(totalsize > maxsize){
+ Object newarr[] = new Object[totalsize*2];
+ System.arraycopy(arr, 0, newarr, 0, cursize);
+ maxsize = maxsize = totalsize * 2;
+ arr = newarr;
+ }
+ System.arraycopy(pool.arr, 0, arr, cursize, srcsize);
+ cursize = totalsize;
+ }
+ public void clear(){
+ cursize = 0;
+ }
}
+
+/**
+ * A simple and efficient class to pool one dimensional byte arrays
+ * of different sizes.
+ */
+class BytePoolDim1 {
+ int maxsize = 256;
+ ObjectPool notusemap[] = new ObjectPool[maxsize];
+ ObjectPool inusemap[] = new ObjectPool[maxsize];
+ byte binit[][] = new byte[maxsize][0];
+
+ public BytePoolDim1(){
+ for(int i = 0; i < maxsize; i++){
+ binit[i] = new byte[i];
+ inusemap[i] = new ObjectPool();
+ notusemap[i] = new ObjectPool();
+ }
+ }
+
+ public byte[] allocByte(int size){
+ if(size > maxsize){
+ return new byte[size];
+ }
+
+ ObjectPool not_usel = notusemap[size];
+ ObjectPool in_usel = inusemap[size];
+ byte b[] = null;
+
+ if(!not_usel.isEmpty()) {
+ Object o = not_usel.remove();
+ b = (byte[]) o;
+ } else
+ b = new byte[size];
+ in_usel.add(b);
+
+ return b;
+ }
+
+ public void deallocate(){
+ for(int i = 0; i < maxsize; i++){
+ notusemap[i].addAll(inusemap[i]);
+ inusemap[i].clear();
+ }
+
+ }
+}
+
+
+
+/**
+ * A simple and efficient class to pool two dimensional byte arrays
+ * of different sizes.
+ */
+class BytePoolDim2 {
+ int maxsize = 32;
+ ObjectPool notusemap[] = new ObjectPool[maxsize];
+ ObjectPool inusemap[] = new ObjectPool[maxsize];
+
+ public BytePoolDim2(){
+ for(int i = 0; i < maxsize; i++){
+ inusemap[i] = new ObjectPool();
+ notusemap[i] = new ObjectPool();
+ }
+ }
+
+ public byte[][] allocByte(int size){
+ if(size > maxsize){
+ return new byte[size][0];
+ }
+ ObjectPool not_usel = notusemap[size];
+ ObjectPool in_usel = inusemap[size];
+
+ byte b[][] = null;
+
+ if(!not_usel.isEmpty()) {
+ Object o = not_usel.remove();
+ b = (byte[][]) o;
+ } else
+ b = new byte[size][0];
+ in_usel.add(b);
+ return b;
+ }
+
+ public void deallocate(){
+ for(int i = 0; i < maxsize; i++){
+ notusemap[i].addAll(inusemap[i]);
+ inusemap[i].clear();
+ }
+ }
+}
+