KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hsqldb > ServerConnection


1 /* Copyright (c) 1995-2000, The Hypersonic SQL Group.
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * Redistributions of source code must retain the above copyright notice, this
8  * list of conditions and the following disclaimer.
9  *
10  * Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  *
14  * Neither the name of the Hypersonic SQL Group nor the names of its
15  * contributors may be used to endorse or promote products derived from this
16  * software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE HYPERSONIC SQL GROUP,
22  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  * This software consists of voluntary contributions made by many individuals
31  * on behalf of the Hypersonic SQL Group.
32  *
33  *
34  * For work added by the HSQL Development Group:
35  *
36  * Copyright (c) 2001-2005, The HSQL Development Group
37  * All rights reserved.
38  *
39  * Redistribution and use in source and binary forms, with or without
40  * modification, are permitted provided that the following conditions are met:
41  *
42  * Redistributions of source code must retain the above copyright notice, this
43  * list of conditions and the following disclaimer.
44  *
45  * Redistributions in binary form must reproduce the above copyright notice,
46  * this list of conditions and the following disclaimer in the documentation
47  * and/or other materials provided with the distribution.
48  *
49  * Neither the name of the HSQL Development Group nor the names of its
50  * contributors may be used to endorse or promote products derived from this
51  * software without specific prior written permission.
52  *
53  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
54  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56  * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
57  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
58  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
59  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
60  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
61  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
62  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
63  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64  */

65
66
67 package org.hsqldb;
68
69 import java.io.BufferedOutputStream JavaDoc;
70 import java.io.DataInputStream JavaDoc;
71 import java.io.IOException JavaDoc;
72 import java.net.Socket JavaDoc;
73
74 import org.hsqldb.lib.ArrayUtil;
75 import org.hsqldb.rowio.RowInputBinary;
76 import org.hsqldb.rowio.RowOutputBinary;
77
78 // fredt@users 20020215 - patch 461556 by paul-h@users - server factory
79
// fredt@users 20020424 - patch 1.7.0 by fredt - shutdown without exit
80
// fredt@users 20021002 - patch 1.7.1 by fredt - changed notification method
81
// fredt@users 20030618 - patch 1.7.2 by fredt - changed read/write methods
82

83 /**
84  * All ServerConnection objects are listed in a Set in server
85  * and removed by this class when closed.<p>
86  *
87  * When the database or server is shutdown, the signalClose() method is called
88  * for all current ServerConnection instances. This will call the private
89  * close() method unless the ServerConnection thread itself has caused the
90  * shutdown. In this case, the keepAlive flag is set to false, allowing the
91  * thread to terminate once it has returned the result of the operation to
92  * the client.
93  * (fredt@users)<p>
94  *
95  * Rewritten in version HSQLDB 1.7.2, based on original Hypersonic code.
96  *
97  * @author Thomas Mueller (Hypersonic SQL Group)
98  * @author fredt@users
99  * @version 1.8.0
100  * @since Hypersonic SQL
101  */

102 class ServerConnection implements Runnable JavaDoc {
103
104     boolean keepAlive;
105     private String JavaDoc user;
106     private String JavaDoc password;
107     int dbID;
108     private volatile Session session;
109     private Socket JavaDoc socket;
110     private Server server;
111     private DataInputStream JavaDoc dataInput;
112     private BufferedOutputStream JavaDoc dataOutput;
113     private static int mCurrentThread = 0;
114     private int mThread;
115     static final int BUFFER_SIZE = 0x1000;
116     final byte[] mainBuffer = new byte[BUFFER_SIZE];
117     RowOutputBinary rowOut = new RowOutputBinary(BUFFER_SIZE);
118     RowInputBinary rowIn = new RowInputBinary(rowOut);
119     Thread JavaDoc runnerThread;
120
121     /**
122      * Creates a new ServerConnection to the specified Server on the
123      * specified socket.
124      *
125      * @param socket the network socket on which Server communication
126      * takes place
127      * @param server the Server instance to which the object
128      * represents a connection
129      */

130     ServerConnection(Socket JavaDoc socket, Server server) {
131
132         this.socket = socket;
133         this.server = server;
134
135         synchronized (ServerConnection.class) {
136             mThread = mCurrentThread++;
137         }
138
139         synchronized (server.serverConnSet) {
140             server.serverConnSet.add(this);
141         }
142     }
143
144     /**
145      * Signals this object to close, including exiting the thread running
146      * the request handling loop
147      */

148     void signalClose() {
149
150         keepAlive = false;
151
152         if (!Thread.currentThread().equals(runnerThread)) {
153             close();
154         }
155     }
156
157     /**
158      * Closes this connection.
159      */

160     private void close() {
161
162         if (session != null) {
163             session.close();
164         }
165
166         session = null;
167
168         // fredt@user - closing the socket is to stop this thread
169
try {
170             socket.close();
171         } catch (IOException JavaDoc e) {}
172
173         synchronized (server.serverConnSet) {
174             server.serverConnSet.remove(this);
175         }
176     }
177
178     /**
179      * Initializes this connection.
180      */

181     private void init() {
182
183         runnerThread = Thread.currentThread();
184         keepAlive = true;
185
186         try {
187             socket.setTcpNoDelay(true);
188
189             dataInput = new DataInputStream JavaDoc(socket.getInputStream());
190             dataOutput = new BufferedOutputStream JavaDoc(socket.getOutputStream());
191
192             Result resultIn = Result.read(rowIn, dataInput);
193             Result resultOut;
194
195             try {
196                 dbID = server.getDBID(resultIn.subSubString);
197                 user = resultIn.getMainString();
198                 password = resultIn.getSubString();
199
200                 if (!server.isSilent()) {
201                     server.printWithThread(mThread
202                                            + ":trying to connect user "
203                                            + user);
204                 }
205
206                 session = DatabaseManager.newSession(dbID,
207                                                      resultIn.getMainString(),
208                                                      resultIn.getSubString());
209                 resultOut = new Result(ResultConstants.UPDATECOUNT);
210                 resultOut.databaseID = session.getDatabase().databaseID;
211                 resultOut.sessionID = session.getId();
212             } catch (HsqlException e) {
213                 session = null;
214                 resultOut = new Result(e, null);
215             } catch (RuntimeException JavaDoc e) {
216                 session = null;
217                 resultOut = new Result(e, null);
218             }
219
220             Result.write(resultOut, rowOut, dataOutput);
221
222             return;
223         } catch (Exception JavaDoc e) {
224             server.printWithThread(mThread + ":couldn't connect " + user);
225         }
226
227         close();
228     }
229
230     /**
231      * Initializes this connection and runs the request handling
232      * loop until closed.
233      */

234     public void run() {
235
236         init();
237
238         if (session != null) {
239             try {
240                 while (keepAlive) {
241                     Result resultIn = Result.read(rowIn, dataInput);
242
243                     server.printRequest(mThread, resultIn);
244
245                     Result resultOut;
246
247                     if (resultIn.mode == ResultConstants.HSQLRESETSESSION) {
248                         resultOut = resetSession();
249                     } else {
250                         resultOut = session.execute(resultIn);
251                     }
252
253                     Result.write(resultOut, rowOut, dataOutput);
254                     rowOut.setBuffer(mainBuffer);
255                     rowIn.resetRow(mainBuffer.length);
256                 }
257             } catch (IOException JavaDoc e) {
258
259                 // fredt - is thrown when connection drops
260
server.printWithThread(mThread + ":disconnected " + user);
261             } catch (HsqlException e) {
262
263                 // fredt - is thrown while constructing the result
264
server.printStackTrace(e);
265             }
266
267             close();
268         }
269     }
270
271     /**
272      * Used by pooled connections to close the existing SQL session and open
273      * a new one.
274      */

275     private Result resetSession() {
276
277         Result resultOut;
278
279         if (!server.isSilent()) {
280             server.printWithThread(mThread + ":trying to connect user "
281                                    + user);
282         }
283
284         try {
285             session.close();
286
287             session = DatabaseManager.newSession(dbID, user, password);
288             resultOut = new Result(ResultConstants.UPDATECOUNT);
289             resultOut.databaseID = session.getDatabase().databaseID;
290             resultOut.sessionID = session.getId();
291         } catch (HsqlException e) {
292             session = null;
293             resultOut = new Result(e, null);
294         }
295
296         return resultOut;
297     }
298
299     /**
300      * Retrieves the thread name to be used when
301      * this object is the Runnable object of a Thread.
302      *
303      * @return the thread name to be used when this object is the Runnable
304      * object of a Thread.
305      */

306     String JavaDoc getConnectionThreadName() {
307         return "HSQLDB Connection @" + Integer.toString(hashCode(), 16);
308     }
309 }
310
Popular Tags