1 //
2 // Copyright 1998 CDS Networks, Inc., Medford Oregon
3 //
4 // All rights reserved.
5 //
6 // Redistribution and use in source and binary forms, with or without
7 // modification, are permitted provided that the following conditions are met:
8 // 1. Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // 2. Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 // 3. All advertising materials mentioning features or use of this software
14 // must display the following acknowledgement:
15 // This product includes software developed by CDS Networks, Inc.
16 // 4. The name of CDS Networks, Inc. may not be used to endorse or promote
17 // products derived from this software without specific prior
18 // written permission.
19 //
20 // THIS SOFTWARE IS PROVIDED BY CDS NETWORKS, INC. ``AS IS'' AND
21 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 // ARE DISCLAIMED. IN NO EVENT SHALL CDS NETWORKS, INC. BE LIABLE
24 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 // OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 // SUCH DAMAGE.
31 //
32
33 package com.internetcds.jdbc.tds;
34
35 /***
36 * This class provides support for canceling queries.
37 * <p>
38 * Basically all threads can be divided into two groups, workers and
39 * cancelers. The canceler can cancel at anytime, even when there is no
40 * outstanding query to cancel. A worker can be in one of 4 states-
41 * <p>
42 * 1) Not doing anything DB related.<br>
43 * 2) currently sending a request to the database. (Note- any time
44 * a request is sent to the DB the DB will send a response. This
45 * means a thread in state 2 must go to state 3.)<br>
46 * 3) waiting for a response from DB<br>
47 * 4) reading the response from DB<br>
48 * <p>
49 * I can easily make it so that only one thread at a time can be in state
50 * 2, 3, or 4.
51 * <p>
52 * The way that a cancel works in TDS is you send a cancel packet to
53 * server. The server will then stop whatever it might be doing and
54 * reply with END_OF_DATA packet with the cancel flag set. (It sends
55 * this packet even if it wasn't doing anything.) I will call this
56 * packet a CANCEL_ACK packet
57 * <p>
58 * All that I really need is to do is make sure that I try to read as
59 * many CANCEL_ACKs as I request and the I make sure that some thread is
60 * out there ready to read any CANCEL_ACKs that i request.
61 * <p>
62 * Clearly if all my worker threads are in state 1 then the cancel
63 * request could be just a nop.
64 * <p>
65 * If I have some worker thread in state 2, 3, or 4 I think I will be fine
66 * if I just make sure that the thread reads until the CANCEL_ACK packet.
67 * <p>
68 * I think I will just have a control object that has one boolean,
69 * readInProgress and two integers, cancelsRequested and
70 * cancelsProcessed.
71 * <p>
72 * <p>
73 * The doCancel() method will-
74 * a) lock the object
75 * b) if there is no read in progress it will unlock and return.
76 * c) otherwise it will send the CANCEL packet,
77 * d) increment the cancelsRequested
78 * e) unlock object and wait until notified that the
79 * cancel was ack'd
80 * <p>
81 * Whenever the worker thread wants to read a response from the DB it
82 * must-
83 * a) lock the control object,<b>
84 * b) set the queryOutstanding flag<b>
85 * c) unlock the control object<b>
86 * d) call the Tds.processSubPacket() method.<b>
87 * e) lock the control object<b>
88 * f) If the packet was a cancel ack it will increment
89 * cancelsProcessed <b>
90 * g) notify any threads that are waiting for cancel acknowledgment<b>
91 * h) unlock the control object.<b>
92 *
93 * @version $Id: CancelController.java,v 1.1 2003/04/29 18:07:50 sinisa Exp $
94 @ @author Craig Spannring
95 */
96 public class CancelController
97 {
98 public static final String cvsVersion = "$Id: CancelController.java,v 1.1 2003/04/29 18:07:50 sinisa Exp $";
99
100
101 boolean awaitingData = false;
102 int cancelsRequested = 0;
103 int cancelsProcessed = 0;
104
105 public synchronized void setQueryInProgressFlag()
106 {
107 awaitingData = true;
108 }
109
110 private synchronized void clearQueryInProgressFlag()
111 {
112 awaitingData = false;
113 }
114
115 public synchronized void finishQuery(
116 boolean wasCanceled,
117 boolean moreResults)
118 {
119 // XXX Do we want to clear the query in progress flag if
120 // there are still more results for multi result set query?
121 // Whatever mechanism is used to handle outstanding query
122 // requires knowing if there is any thread out there that could
123 // still process the query acknowledgment. Prematurely clearing
124 // could cause data to be thrown out before the thread expecting
125 // the data gets a chance to process it. That could cause the
126 // thread to read some other threads query.
127 //
128 // Is it good enough to just look at the MORERESULTS bit in the
129 // TDS_END* packet and not clear the flag if we have more
130 // results?
131 if (! moreResults)
132 {
133 clearQueryInProgressFlag();
134 }
135
136 if (wasCanceled)
137 {
138 handleCancelAck();
139 }
140
141 // XXX Should we see if there are any more cancels pending and
142 // try to read the cancel acknowledgments?
143 }
144
145
146 public synchronized void doCancel(TdsComm comm)
147 throws java.io.IOException
148 {
149 if (awaitingData)
150 {
151 comm.startPacket(TdsComm.CANCEL);
152 comm.sendPacket();
153 cancelsRequested++;
154
155
156 while(cancelsRequested > cancelsProcessed)
157 {
158 try
159 {
160 wait();
161 // XXX If there are cancels pending but nobody is is
162 // awaiting data on this connection, should we go out
163 // and try to get the CANCELACK packet?
164 }
165 catch(java.lang.InterruptedException e)
166 {
167 // nop
168 }
169 }
170 }
171 else
172 {
173 // if we aren't waiting for anything from
174 // the server then we have nothing to cancel
175
176 // nop
177 }
178 }
179
180
181
182 private synchronized void handleCancelAck()
183 {
184 cancelsProcessed++;
185 notify();
186 }
187 }
This page was automatically generated by Maven