1 | /* |
2 | |
3 | Derby - Class org.apache.derby.client.net.NetXAConnectionReply |
4 | |
5 | Copyright (c) 2001, 2005 The Apache Software Foundation or its licensors, where applicable. |
6 | |
7 | Licensed under the Apache License, Version 2.0 (the "License"); |
8 | you may not use this file except in compliance with the License. |
9 | You may obtain a copy of the License at |
10 | |
11 | http://www.apache.org/licenses/LICENSE-2.0 |
12 | |
13 | Unless required by applicable law or agreed to in writing, software |
14 | distributed under the License is distributed on an "AS IS" BASIS, |
15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
16 | See the License for the specific language governing permissions and |
17 | limitations under the License. |
18 | |
19 | */ |
20 | |
21 | package org.apache.derby.client.net; |
22 | |
23 | import javax.transaction.xa.XAResource; |
24 | import javax.transaction.xa.Xid; |
25 | |
26 | import org.apache.derby.client.am.ConnectionCallbackInterface; |
27 | import org.apache.derby.client.am.DisconnectException; |
28 | |
29 | public class NetXAConnectionReply extends NetResultSetReply { |
30 | NetXAConnectionReply(NetAgent netAgent, int bufferSize) { |
31 | super(netAgent, bufferSize); |
32 | } |
33 | //----------------------------- entry points --------------------------------- |
34 | |
35 | |
36 | public void readLocalXAStart(ConnectionCallbackInterface connection) throws DisconnectException { |
37 | } |
38 | |
39 | public void readLocalXACommit(ConnectionCallbackInterface connection) throws DisconnectException { |
40 | |
41 | startSameIdChainParse(); |
42 | parseSYNCCTLreply(connection); |
43 | endOfSameIdChainData(); |
44 | |
45 | NetXACallInfo callInfo = |
46 | netAgent_.netConnection_.xares_.callInfoArray_[netAgent_.netConnection_.currXACallInfoOffset_]; |
47 | callInfo.xaInProgress_ = false; |
48 | callInfo.xaWasSuspended = false; |
49 | connection.completeLocalCommit(); |
50 | } |
51 | |
52 | public void readLocalXARollback(ConnectionCallbackInterface connection) throws DisconnectException { |
53 | startSameIdChainParse(); |
54 | parseSYNCCTLreply(connection); |
55 | endOfSameIdChainData(); |
56 | connection.completeLocalRollback(); |
57 | } |
58 | |
59 | protected void readXaStartUnitOfWork(NetConnection conn) throws DisconnectException { |
60 | startSameIdChainParse(); |
61 | parseSYNCCTLreply(conn); |
62 | endOfSameIdChainData(); |
63 | } |
64 | |
65 | protected int readXaEndUnitOfWork(NetConnection conn) throws DisconnectException { |
66 | NetXACallInfo callInfo = conn.xares_.callInfoArray_[conn.currXACallInfoOffset_]; |
67 | int xaFlags = callInfo.xaFlags_; |
68 | |
69 | startSameIdChainParse(); |
70 | parseSYNCCTLreply(conn); |
71 | endOfSameIdChainData(); |
72 | if (xaFlags == XAResource.TMFAIL) { |
73 | return javax.transaction.xa.XAException.XA_RBROLLBACK; |
74 | } |
75 | return javax.transaction.xa.XAResource.XA_OK; |
76 | } |
77 | |
78 | protected int readXaPrepare(NetConnection conn) throws DisconnectException { |
79 | startSameIdChainParse(); |
80 | int synctype = parseSYNCCTLreply(conn); |
81 | endOfSameIdChainData(); |
82 | |
83 | NetXACallInfo callInfo = conn.xares_.callInfoArray_[conn.currXACallInfoOffset_]; |
84 | if (synctype == XAResource.XA_RDONLY) { // xaretval of read-only, make sure flag agrees |
85 | callInfo.setReadOnlyTransactionFlag(true); |
86 | } else { // xaretval NOT read-only, make sure flag agrees |
87 | callInfo.setReadOnlyTransactionFlag(false); |
88 | } |
89 | return synctype; |
90 | } |
91 | |
92 | protected void readXaCommit(NetConnection conn) throws DisconnectException { |
93 | startSameIdChainParse(); |
94 | parseSYNCCTLreply(conn); |
95 | endOfSameIdChainData(); |
96 | |
97 | NetXACallInfo callInfo = conn.xares_.callInfoArray_[conn.currXACallInfoOffset_]; |
98 | callInfo.xaInProgress_ = false; |
99 | conn.completeLocalCommit(); |
100 | } |
101 | |
102 | protected int readXaRollback(NetConnection conn) throws DisconnectException { |
103 | startSameIdChainParse(); |
104 | parseSYNCCTLreply(conn); |
105 | endOfSameIdChainData(); |
106 | |
107 | NetXACallInfo callInfo = conn.xares_.callInfoArray_[conn.currXACallInfoOffset_]; |
108 | callInfo.xaInProgress_ = false; |
109 | callInfo.xaWasSuspended = false; |
110 | conn.completeLocalRollback(); |
111 | |
112 | return javax.transaction.xa.XAResource.XA_OK; |
113 | } |
114 | |
115 | protected void readXaRecover(NetConnection conn) throws DisconnectException { |
116 | startSameIdChainParse(); |
117 | parseSYNCCTLreply(conn); |
118 | endOfSameIdChainData(); |
119 | } |
120 | |
121 | protected void readXaForget(NetConnection conn) throws DisconnectException { |
122 | startSameIdChainParse(); |
123 | parseSYNCCTLreply(conn); |
124 | endOfSameIdChainData(); |
125 | } |
126 | //----------------------helper methods---------------------------------------- |
127 | |
128 | //--------------------- parse DDM Reply Data-------------------------------------- |
129 | |
130 | |
131 | // The SYNCCRD Reply Mesage |
132 | // |
133 | // Returned from Server: |
134 | // XARETVAL - required |
135 | int parseSYNCCRD(ConnectionCallbackInterface connection) throws DisconnectException { |
136 | boolean svrcodReceived = false; |
137 | int svrcod = CodePoint.SVRCOD_INFO; |
138 | int xaretval = 0; |
139 | int synctype = 0; |
140 | java.util.Hashtable indoubtTransactions = null; |
141 | NetConnection conn = netAgent_.netConnection_; |
142 | |
143 | parseLengthAndMatchCodePoint(CodePoint.SYNCCRD); |
144 | pushLengthOnCollectionStack(); |
145 | int peekCP = peekCodePoint(); |
146 | |
147 | while (peekCP != Reply.END_OF_COLLECTION) { |
148 | |
149 | boolean foundInPass = false; |
150 | |
151 | if (peekCP == CodePoint.SVRCOD) { |
152 | foundInPass = true; |
153 | svrcodReceived = checkAndGetReceivedFlag(svrcodReceived); |
154 | svrcod = parseSVRCOD(CodePoint.SVRCOD_ERROR, CodePoint.SVRCOD_ERROR); |
155 | peekCP = peekCodePoint(); |
156 | } |
157 | |
158 | if (peekCP == CodePoint.XARETVAL) { |
159 | foundInPass = true; |
160 | xaretval = parseXARETVAL(); |
161 | conn.xares_.callInfoArray_[conn.currXACallInfoOffset_].xaRetVal_ = |
162 | xaretval; |
163 | peekCP = peekCodePoint(); |
164 | } |
165 | |
166 | if (peekCP == CodePoint.SYNCTYPE) { |
167 | foundInPass = true; |
168 | synctype = parseSYNCTYPE(); |
169 | peekCP = peekCodePoint(); |
170 | } |
171 | |
172 | if (peekCP == CodePoint.PRPHRCLST) { |
173 | foundInPass = true; |
174 | indoubtTransactions = parseIndoubtList(); |
175 | conn.setIndoubtTransactions(indoubtTransactions); |
176 | peekCP = peekCodePoint(); |
177 | } |
178 | |
179 | if (!foundInPass) { |
180 | doPrmnsprmSemantics(peekCP); |
181 | } |
182 | } |
183 | popCollectionStack(); |
184 | |
185 | |
186 | return xaretval; |
187 | |
188 | } |
189 | |
190 | // Process XA return value |
191 | protected int parseXARETVAL() throws DisconnectException { |
192 | parseLengthAndMatchCodePoint(CodePoint.XARETVAL); |
193 | return readInt(); |
194 | } |
195 | |
196 | // Process XA return value |
197 | protected byte parseSYNCTYPE() throws DisconnectException { |
198 | parseLengthAndMatchCodePoint(CodePoint.SYNCTYPE); |
199 | return readByte(); |
200 | } |
201 | |
202 | // This method handles the parsing of all command replies and reply data |
203 | // for the SYNNCTL command. |
204 | protected int parseSYNCCTLreply(ConnectionCallbackInterface connection) throws DisconnectException { |
205 | int retval = 0; |
206 | int peekCP = peekCodePoint(); |
207 | |
208 | if (peekCP != CodePoint.SYNCCRD) { |
209 | parseSYNCCTLError(peekCP); |
210 | return -1; |
211 | } |
212 | retval = parseSYNCCRD(connection); |
213 | |
214 | peekCP = peekCodePoint(); |
215 | while (peekCP == CodePoint.SQLSTT) { |
216 | String s = parseSQLSTT(); |
217 | //JCFTMP, need to null out the client list? |
218 | netAgent_.netConnection_.xares_.addSpecialRegisters(s); |
219 | peekCP = peekCodePoint(); |
220 | } |
221 | |
222 | return retval; |
223 | } |
224 | |
225 | |
226 | //------------------------parse DDM Scalars----------------------------- |
227 | |
228 | |
229 | |
230 | |
231 | private String parseSQLSTT() throws DisconnectException { |
232 | parseLengthAndMatchCodePoint(CodePoint.SQLSTT); |
233 | return parseSQLSTTGRPNOCMorNOCS(); |
234 | } |
235 | |
236 | private String parseSQLSTTGRPNOCMorNOCS() throws DisconnectException { |
237 | int mixedNullInd = readUnsignedByte(); |
238 | int singleNullInd = 0; |
239 | String sqlsttString = null; |
240 | int stringLength = 0; |
241 | |
242 | if (mixedNullInd == CodePoint.NULLDATA) { |
243 | singleNullInd = readUnsignedByte(); |
244 | if (singleNullInd == CodePoint.NULLDATA) { |
245 | // throw DTAMCHRM |
246 | doDtamchrmSemantics(); |
247 | } |
248 | // read 4-byte length |
249 | stringLength = readInt(); |
250 | // read sqlstt string |
251 | sqlsttString = readString(stringLength, netAgent_.targetTypdef_.getCcsidSbcEncoding()); |
252 | } else { |
253 | // read 4-byte length |
254 | stringLength = readInt(); |
255 | // read sqlstt string |
256 | sqlsttString = readString(stringLength, netAgent_.targetTypdef_.getCcsidMbcEncoding()); |
257 | // read null indicator |
258 | singleNullInd = readUnsignedByte(); |
259 | } |
260 | return sqlsttString; |
261 | } |
262 | |
263 | |
264 | protected int parseXIDCNT() throws DisconnectException { |
265 | parseLengthAndMatchCodePoint(CodePoint.XIDCNT); |
266 | return readUnsignedShort(); |
267 | } |
268 | |
269 | protected Xid parseXID() throws DisconnectException { |
270 | parseLengthAndMatchCodePoint(CodePoint.XID); |
271 | int formatId = readInt(); |
272 | int gtridLen = readInt(); |
273 | int bqualLen = readInt(); |
274 | byte[] gtrid = readBytes(gtridLen); |
275 | byte[] bqual = readBytes(bqualLen); |
276 | |
277 | return new org.apache.derby.client.ClientXid(formatId, gtrid, bqual); |
278 | } |
279 | |
280 | protected java.util.Hashtable parseIndoubtList() throws DisconnectException { |
281 | boolean found = false; |
282 | int port = 0; |
283 | int numXid = 0; |
284 | String sIpAddr = null; |
285 | int peekCP = peekCodePoint(); |
286 | parseLengthAndMatchCodePoint(CodePoint.PRPHRCLST); |
287 | peekCP = peekCodePoint(); |
288 | if (peekCP == CodePoint.XIDCNT) { |
289 | found = true; |
290 | numXid = parseXIDCNT(); |
291 | peekCP = peekCodePoint(); |
292 | } |
293 | |
294 | java.util.Hashtable indoubtTransactions = new java.util.Hashtable(); |
295 | while (peekCP == CodePoint.XID) { |
296 | Xid xid = parseXID(); |
297 | indoubtTransactions.put(xid, new NetIndoubtTransaction(xid, null, null, null, sIpAddr, port)); |
298 | peekCP = peekCodePoint(); |
299 | } |
300 | |
301 | return indoubtTransactions; |
302 | } |
303 | |
304 | } |
305 | |
306 | |
307 | |