Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit25b5faa

Browse files
committed
Just a quick patch. This makes the JDBC driver thread safe, which is an
important step towards making the driver compliant, and means that forsome Java applications and servlets, only a single database connectionisneeded, so in a sence this is a nice little show stopper for 6.4 (andshould still be backward compatible to 6.3.2).Peter
1 parent9042e9d commit25b5faa

File tree

4 files changed

+368
-4
lines changed

4 files changed

+368
-4
lines changed

‎src/interfaces/jdbc/Makefile

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# Makefile for Java JDBC interface
55
#
66
# IDENTIFICATION
7-
# $Header: /cvsroot/pgsql/src/interfaces/jdbc/Attic/Makefile,v 1.9 1998/09/03 02:29:41 momjian Exp $
7+
# $Header: /cvsroot/pgsql/src/interfaces/jdbc/Attic/Makefile,v 1.10 1998/10/08 00:38:18 momjian Exp $
88
#
99
#-------------------------------------------------------------------------
1010

@@ -137,7 +137,8 @@ EX=example/basic.class \
137137
example/datestyle.class\
138138
example/psql.class\
139139
example/ImageViewer.class\
140-
example/metadata.class
140+
example/metadata.class\
141+
example/threadsafe.class
141142
#example/Objects.class
142143

143144
# This rule builds the examples
@@ -160,7 +161,9 @@ examples:postgresql.jar $(EX)
160161
@echo" example.psql Simple java implementation of psql"
161162
@echo" example.Objects Demonstrates Object Serialisation"
162163
@echo""
164+
@echo These are not really examples, but tests various parts of the driver
163165
@echo" example.metadata Tests various metadata methods"
166+
@echo" example.threadsafe Tests the driver's thread safety"
164167
@echo ------------------------------------------------------------
165168
@echo
166169

@@ -170,6 +173,6 @@ example/datestyle.class:example/datestyle.java
170173
example/psql.class:example/psql.java
171174
example/ImageViewer.class:example/ImageViewer.java
172175
#example/Objects.class:example/Objects.java
173-
176+
example/threadsafe.class:example/threadsafe.java
174177
example/metadata.class:example/metadata.java
175178
#######################################################################
Lines changed: 353 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,353 @@
1+
packageexample;
2+
3+
importjava.io.*;
4+
importjava.sql.*;
5+
importjava.text.*;
6+
7+
// rare in user code, but we use the LargeObject API in this test
8+
importpostgresql.largeobject.*;
9+
10+
/**
11+
* This example tests the thread safety of the driver.
12+
*
13+
* It does this by performing several queries, in different threads. Each
14+
* thread has it's own Statement object, which is (in my understanding of the
15+
* jdbc specification) the minimum requirement.
16+
*
17+
*/
18+
19+
publicclassthreadsafe
20+
{
21+
Connectiondb;// The connection to the database
22+
Statementst;// Our statement to run queries with
23+
24+
publicthreadsafe(Stringargs[])throwsClassNotFoundException,FileNotFoundException,IOException,SQLException
25+
{
26+
Stringurl =args[0];
27+
Stringusr =args[1];
28+
Stringpwd =args[2];
29+
30+
// Load the driver
31+
Class.forName("postgresql.Driver");
32+
33+
// Connect to database
34+
System.out.println("Connecting to Database URL = " +url);
35+
db =DriverManager.getConnection(url,usr,pwd);
36+
37+
System.out.println("Connected...Now creating a statement");
38+
st =db.createStatement();
39+
40+
// Clean up the database (in case we failed earlier) then initialise
41+
cleanup();
42+
43+
// Now run tests using JDBC methods, then LargeObjects
44+
doexample();
45+
46+
// Clean up the database
47+
cleanup();
48+
49+
// Finally close the database
50+
System.out.println("Now closing the connection");
51+
st.close();
52+
db.close();
53+
54+
}
55+
56+
/**
57+
* This drops the table (if it existed). No errors are reported.
58+
*/
59+
publicvoidcleanup()
60+
{
61+
try {
62+
st.executeUpdate("drop table basic");
63+
}catch(Exceptionex) {
64+
// We ignore any errors here
65+
}
66+
}
67+
68+
/**
69+
* This performs the example
70+
*/
71+
publicvoiddoexample()throwsSQLException
72+
{
73+
System.out.println("\nThis test runs three Threads. Two simply insert data into a table, then\nthey perform a query. While they are running, a third thread is running,\nand it load data into, then reads from a Large Object.\n\nIf alls well, this should run without any errors. If so, we are Thread Safe.\nWhy test JDBC & LargeObject's? Because both will run over the network\nconnection, and if locking on the stream isn't done correctly, the backend\nwill get pretty confused!\n");
74+
75+
thread3thread3=null;
76+
77+
try {
78+
79+
// create the two threads
80+
Threadthread0 =Thread.currentThread();
81+
Threadthread1 =newthread1(db);
82+
Threadthread2 =newthread2(db);
83+
thread3 =newthread3(db);
84+
85+
// now run, and wait for them
86+
thread1.start();
87+
thread2.start();
88+
thread3.start();
89+
90+
// ok, I know this is bad, but it does the trick here as our main thread
91+
// will yield as long as either of the children are still running
92+
System.out.println("Waiting for threads to run");
93+
while(thread1.isAlive() ||thread2.isAlive() ||thread3.isAlive())
94+
thread0.yield();
95+
96+
}finally {
97+
// clean up after thread3 (the finally ensures this is run even
98+
// if an exception is thrown inside the try { } construct)
99+
if(thread3 !=null)
100+
thread3.cleanup();
101+
}
102+
103+
System.out.println("No Exceptions have been thrown. This is a good omen, as it means that we are\npretty much thread safe as we can get.");
104+
}
105+
106+
// This is the first thread. It's the same as the basic test
107+
classthread1extendsThread
108+
{
109+
Connectionc;
110+
Statementst;
111+
112+
publicthread1(Connectionc)throwsSQLException {
113+
this.c =c;
114+
st =c.createStatement();
115+
}
116+
117+
publicvoidrun() {
118+
try {
119+
System.out.println("Thread 1 running...");
120+
121+
// First we need a table to store data in
122+
st.executeUpdate("create table basic (a int2, b int2)");
123+
124+
// Now insert some data, using the Statement
125+
st.executeUpdate("insert into basic values (1,1)");
126+
st.executeUpdate("insert into basic values (2,1)");
127+
st.executeUpdate("insert into basic values (3,1)");
128+
129+
// For large inserts, a PreparedStatement is more efficient, because it
130+
// supports the idea of precompiling the SQL statement, and to store
131+
// directly, a Java object into any column. PostgreSQL doesnt support
132+
// precompiling, but does support setting a column to the value of a
133+
// Java object (like Date, String, etc).
134+
//
135+
// Also, this is the only way of writing dates in a datestyle independent
136+
// manner. (DateStyles are PostgreSQL's way of handling different methods
137+
// of representing dates in the Date data type.)
138+
PreparedStatementps =db.prepareStatement("insert into basic values (?,?)");
139+
for(inti=2;i<200;i++) {
140+
ps.setInt(1,4);// "column a" = 5
141+
ps.setInt(2,i);// "column b" = i
142+
ps.executeUpdate();// executeUpdate because insert returns no data
143+
if((i%50)==0)
144+
DriverManager.println("Thread 1 done "+i+" inserts");
145+
}
146+
ps.close();// Always close when we are done with it
147+
148+
// Finally perform a query on the table
149+
DriverManager.println("Thread 1 performing a query");
150+
ResultSetrs =st.executeQuery("select a, b from basic");
151+
intcnt=0;
152+
if(rs!=null) {
153+
// Now we run through the result set, printing out the result.
154+
// Note, we must call .next() before attempting to read any results
155+
while(rs.next()) {
156+
inta =rs.getInt("a");// This shows how to get the value by name
157+
intb =rs.getInt(2);// This shows how to get the value by column
158+
//System.out.println(" a="+a+" b="+b);
159+
cnt++;
160+
}
161+
rs.close();// again, you must close the result when done
162+
}
163+
DriverManager.println("Thread 1 read "+cnt+" rows");
164+
165+
// The last thing to do is to drop the table. This is done in the
166+
// cleanup() method.
167+
System.out.println("Thread 1 finished");
168+
}catch(SQLExceptionse) {
169+
System.err.println("Thread 1: "+se.toString());
170+
se.printStackTrace();
171+
System.exit(1);
172+
}
173+
}
174+
}
175+
176+
// This is the second thread. It's the similar to the basic test, and thread1
177+
// except it works on another table.
178+
classthread2extendsThread
179+
{
180+
Connectionc;
181+
Statementst;
182+
183+
publicthread2(Connectionc)throwsSQLException {
184+
this.c =c;
185+
st =c.createStatement();
186+
}
187+
188+
publicvoidrun() {
189+
try {
190+
System.out.println("Thread 2 running...");
191+
192+
// For large inserts, a PreparedStatement is more efficient, because it
193+
// supports the idea of precompiling the SQL statement, and to store
194+
// directly, a Java object into any column. PostgreSQL doesnt support
195+
// precompiling, but does support setting a column to the value of a
196+
// Java object (like Date, String, etc).
197+
//
198+
// Also, this is the only way of writing dates in a datestyle independent
199+
// manner. (DateStyles are PostgreSQL's way of handling different methods
200+
// of representing dates in the Date data type.)
201+
PreparedStatementps =db.prepareStatement("insert into basic values (?,?)");
202+
for(inti=2;i<200;i++) {
203+
ps.setInt(1,4);// "column a" = 5
204+
ps.setInt(2,i);// "column b" = i
205+
ps.executeUpdate();// executeUpdate because insert returns no data
206+
if((i%50)==0)
207+
DriverManager.println("Thread 2 done "+i+" inserts");
208+
}
209+
ps.close();// Always close when we are done with it
210+
211+
// Finally perform a query on the table
212+
DriverManager.println("Thread 2 performing a query");
213+
ResultSetrs =st.executeQuery("select * from basic where b>1");
214+
intcnt=0;
215+
if(rs!=null) {
216+
// First find out the column numbers.
217+
//
218+
// It's best to do this here, as calling the methods with the column
219+
// numbers actually performs this call each time they are called. This
220+
// really speeds things up on large queries.
221+
//
222+
intcol_a =rs.findColumn("a");
223+
intcol_b =rs.findColumn("b");
224+
225+
// Now we run through the result set, printing out the result.
226+
// Again, we must call .next() before attempting to read any results
227+
while(rs.next()) {
228+
inta =rs.getInt(col_a);// This shows how to get the value by name
229+
intb =rs.getInt(col_b);// This shows how to get the value by column
230+
//System.out.println(" a="+a+" b="+b);
231+
cnt++;
232+
}
233+
rs.close();// again, you must close the result when done
234+
}
235+
DriverManager.println("Thread 2 read "+cnt+" rows");
236+
237+
// The last thing to do is to drop the table. This is done in the
238+
// cleanup() method.
239+
System.out.println("Thread 2 finished");
240+
}catch(SQLExceptionse) {
241+
System.err.println("Thread 2: "+se.toString());
242+
se.printStackTrace();
243+
System.exit(1);
244+
}
245+
}
246+
}
247+
248+
// This is the third thread. It loads, then reads from a LargeObject, using
249+
// our LargeObject api.
250+
//
251+
// The purpose of this is to test that FastPath will work in between normal
252+
// JDBC queries.
253+
classthread3extendsThread
254+
{
255+
Connectionc;
256+
Statementst;
257+
LargeObjectManagerlom;
258+
LargeObjectlo;
259+
intoid;
260+
261+
publicthread3(Connectionc)throwsSQLException {
262+
this.c =c;
263+
//st = c.createStatement();
264+
265+
// create a blob
266+
lom = ((postgresql.Connection)c).getLargeObjectAPI();
267+
oid =lom.create();
268+
System.out.println("Thread 3 has created a blob of oid "+oid);
269+
}
270+
271+
publicvoidrun() {
272+
try {
273+
System.out.println("Thread 3 running...");
274+
275+
DriverManager.println("Thread 3: Loading data into blob "+oid);
276+
lo =lom.open(oid);
277+
FileInputStreamfis =newFileInputStream("example/threadsafe.java");
278+
// keep the buffer size small, to allow the other thread a chance
279+
bytebuf[] =newbyte[128];
280+
intrc,bc=1,bs=0;
281+
while((rc=fis.read(buf))>0) {
282+
DriverManager.println("Thread 3 read block "+bc+" "+bs+" bytes");
283+
lo.write(buf,0,rc);
284+
bc++;
285+
bs+=rc;
286+
}
287+
lo.close();
288+
fis.close();
289+
290+
DriverManager.println("Thread 3: Reading blob "+oid);
291+
lo=lom.open(oid);
292+
bc=0;
293+
while(buf.length>0) {
294+
buf=lo.read(buf.length);
295+
if(buf.length>0) {
296+
Strings =newString(buf);
297+
bc++;
298+
DriverManager.println("Thread 3 block "+bc);
299+
DriverManager.println("Block "+bc+" got "+s);
300+
}
301+
}
302+
lo.close();
303+
304+
System.out.println("Thread 3 finished");
305+
}catch(Exceptionse) {
306+
System.err.println("Thread 3: "+se.toString());
307+
se.printStackTrace();
308+
System.exit(1);
309+
}
310+
}
311+
312+
publicvoidcleanup()throwsSQLException {
313+
if(lom!=null &&oid!=0) {
314+
System.out.println("Thread 3: Removing blob oid="+oid);
315+
lom.delete(oid);
316+
}
317+
}
318+
}
319+
320+
/**
321+
* Display some instructions on how to run the example
322+
*/
323+
publicstaticvoidinstructions()
324+
{
325+
System.out.println("\nThis tests the thread safety of the driver.\n\nThis is done in two parts, the first with standard JDBC calls, and the\nsecond mixing FastPath and LargeObject calls with queries.\n");
326+
System.out.println("Useage:\n java example.threadsafe jdbc:postgresql:database user password [debug]\n\nThe debug field can be anything. It's presence will enable DriverManager's\ndebug trace. Unless you want to see screens of items, don't put anything in\nhere.");
327+
System.exit(1);
328+
}
329+
330+
/**
331+
* This little lot starts the test
332+
*/
333+
publicstaticvoidmain(Stringargs[])
334+
{
335+
System.out.println("PostgreSQL Thread Safety test v6.4 rev 1\n");
336+
337+
if(args.length<3)
338+
instructions();
339+
340+
// This line outputs debug information to stderr. To enable this, simply
341+
// add an extra parameter to the command line
342+
if(args.length>3)
343+
DriverManager.setLogStream(System.err);
344+
345+
// Now run the tests
346+
try {
347+
threadsafetest =newthreadsafe(args);
348+
}catch(Exceptionex) {
349+
System.err.println("Exception caught.\n"+ex);
350+
ex.printStackTrace();
351+
}
352+
}
353+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp