001: /*
002:
003: Derby - Class org.apache.derby.client.am.Agent
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to You under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.client.am;
023:
024: import org.apache.derby.shared.common.reference.SQLState;
025:
026: public abstract class Agent {
027: public SqlException accumulatedReadExceptions_ = null;
028:
029: private boolean enableBatchedExceptionTracking_;
030: private int batchedExceptionLabelIndex_;
031: private boolean[] batchedExceptionGenerated_;
032:
033: Connection connection_; // made friendly for lobs only, refactor !!
034: public SectionManager sectionManager_ = null; // temporarily public, make friendly at least !!
035:
036: public LogWriter logWriter_ = null;
037:
038: final CrossConverters crossConverters_;
039:
040: // Exceptions that occur on dnc's implementation of SqlException.getMessage() via stored proc
041: // cannot be thrown on the getMessage() invocation because the signature of getMessage() does not
042: // allow for throwing an exception.
043: // Therefore, we must save the exception and throw it at our very first opportunity.
044: SqlException deferredException_;
045:
046: void checkForDeferredExceptions() throws SqlException {
047: if (deferredException_ != null) {
048: SqlException temp = deferredException_;
049: deferredException_ = null;
050: throw temp;
051: }
052: }
053:
054: public void accumulateDeferredException(SqlException e) {
055: if (deferredException_ == null) {
056: deferredException_ = e;
057: } else {
058: deferredException_.setNextException(e);
059: }
060: }
061:
062: protected Agent(Connection connection, LogWriter logWriter) {
063: connection_ = connection;
064: logWriter_ = logWriter;
065: crossConverters_ = new CrossConverters(this );
066: }
067:
068: protected void resetAgent(LogWriter logWriter) {
069: // sectionManager_ is set elsewhere
070: accumulatedReadExceptions_ = null;
071: enableBatchedExceptionTracking_ = false;
072: batchedExceptionLabelIndex_ = 0;
073: batchedExceptionGenerated_ = null;
074: logWriter_ = logWriter;
075: deferredException_ = null;
076: }
077:
078: public void resetAgent(Connection connection, LogWriter logWriter,
079: int loginTimeout, String server, int port)
080: throws SqlException {
081: resetAgent(logWriter);
082: resetAgent_(logWriter, loginTimeout, server, port);
083: }
084:
085: abstract protected void resetAgent_(LogWriter logWriter,
086: int loginTimeout, String server, int port)
087: throws SqlException;
088:
089: //-------------------- entry points ------------------------------------------
090:
091: public final boolean loggingEnabled() {
092: return !org.apache.derby.client.am.Configuration.traceSuspended__
093: && logWriter_ != null;
094: }
095:
096: public final void setLogWriter(LogWriter logWriter) {
097: synchronized (connection_) {
098: if (logWriter_ != null) {
099: logWriter_.close();
100: }
101: logWriter_ = logWriter;
102: }
103: }
104:
105: public final java.io.PrintWriter getLogWriter() {
106: return (logWriter_ == null) ? null : logWriter_.printWriter_;
107: }
108:
109: abstract public LogWriter newLogWriter_(
110: java.io.PrintWriter printWriter, int traceLevel);
111:
112: //----------------------------------------------------------------------------
113:
114: public final void accumulateReadException(SqlException e) {
115: if (enableBatchedExceptionTracking_) {
116: batchedExceptionGenerated_[batchedExceptionLabelIndex_] = true;
117: labelAsBatchedException(e, batchedExceptionLabelIndex_);
118: }
119: if (accumulatedReadExceptions_ == null) {
120: accumulatedReadExceptions_ = e;
121: } else {
122: accumulatedReadExceptions_.setNextException(e);
123: }
124: }
125:
126: // Called only for disconnect event
127: public final void accumulateDisconnectException(
128: DisconnectException e) {
129: if (enableBatchedExceptionTracking_) {
130: batchedExceptionGenerated_[batchedExceptionLabelIndex_] = true;
131: labelAsBatchedException(e, batchedExceptionLabelIndex_);
132: }
133: if (accumulatedReadExceptions_ != null) {
134: e.setNextException(accumulatedReadExceptions_);
135: }
136:
137: accumulatedReadExceptions_ = null;
138: }
139:
140: // For now, it looks like the only time we accumulate chain breaking exceptions
141: // is for disconnect exceptions.
142: public final void accumulateChainBreakingReadExceptionAndThrow(
143: DisconnectException e) throws DisconnectException {
144: accumulateDisconnectException(e); // tacks disconnect exc to end of chain
145: markChainBreakingException_(); // sets a severity code in the NET agent
146: throw e; // disconnect will be caught in Reply classes, and front of original chain thrown
147: }
148:
149: abstract protected void markChainBreakingException_();
150:
151: abstract public void checkForChainBreakingException_()
152: throws SqlException;
153:
154: private final void enableBatchedExceptionTracking(int batchSize) {
155: enableBatchedExceptionTracking_ = true;
156: batchedExceptionGenerated_ = new boolean[batchSize];
157: batchedExceptionLabelIndex_ = 0;
158: }
159:
160: final void disableBatchedExceptionTracking() {
161: enableBatchedExceptionTracking_ = false;
162: }
163:
164: public final void setBatchedExceptionLabelIndex(int index) {
165: batchedExceptionLabelIndex_ = index;
166: }
167:
168: private final SqlException labelAsBatchedException(SqlException e,
169: int index) {
170: SqlException firstInChain = e;
171: while (e != null) {
172: e.setBatchPositionLabel(index);
173: e = (SqlException) e.getNextException();
174: }
175: return firstInChain;
176: }
177:
178: protected final void checkForExceptions() throws SqlException {
179: if (accumulatedReadExceptions_ != null) {
180: SqlException e = accumulatedReadExceptions_;
181: accumulatedReadExceptions_ = null;
182: throw e;
183: }
184: }
185:
186: // precondition: all batch execute reads have occurred
187: final boolean batchUpdateExceptionGenerated() {
188: return batchedExceptionGenerated_[batchedExceptionLabelIndex_];
189: }
190:
191: public final void flow(Statement statement) throws SqlException {
192: endWriteChain();
193: flush_();
194: beginReadChain(statement);
195: }
196:
197: public final void flowBatch(Statement statement, int batchSize)
198: throws SqlException {
199: endBatchedWriteChain();
200: flush_();
201: beginBatchedReadChain(statement, batchSize);
202: }
203:
204: public final void flowOutsideUOW() throws SqlException {
205: endWriteChain();
206: flush_();
207: beginReadChainOutsideUOW();
208: }
209:
210: // flush() means to send all chained requests.
211: abstract public void flush_() throws DisconnectException;
212:
213: // Close client resources associated with this agent, such as socket and streams for the net.
214: abstract public void close_() throws SqlException;
215:
216: public void close() throws SqlException {
217: close_();
218: if (logWriter_ != null) {
219: logWriter_.close();
220: }
221: }
222:
223: public final void disconnectEvent() {
224: // closes client-side resources associated with database connection
225: try {
226: close();
227: } catch (SqlException doNothing) {
228: }
229: connection_.completeChainBreakingDisconnect();
230: }
231:
232: public void beginWriteChainOutsideUOW() throws SqlException {
233: }
234:
235: public void beginWriteChain(Statement statement)
236: throws SqlException {
237: connection_.writeTransactionStart(statement);
238: }
239:
240: public final void beginBatchedWriteChain(Statement statement)
241: throws SqlException {
242: beginWriteChain(statement);
243: }
244:
245: protected void endWriteChain() {
246: }
247:
248: protected final void endBatchedWriteChain() {
249: }
250:
251: protected void beginReadChain(Statement statement)
252: throws SqlException {
253: connection_.readTransactionStart();
254: }
255:
256: protected final void beginBatchedReadChain(Statement statement,
257: int batchSize) throws SqlException {
258: enableBatchedExceptionTracking(batchSize);
259: beginReadChain(statement);
260: }
261:
262: protected void beginReadChainOutsideUOW() throws SqlException {
263: }
264:
265: public void endReadChain() throws SqlException {
266: checkForExceptions();
267: }
268:
269: public final void endBatchedReadChain(int[] updateCounts,
270: SqlException accumulatedExceptions)
271: throws BatchUpdateException {
272: disableBatchedExceptionTracking();
273: for (int i = 0; i < batchedExceptionGenerated_.length; i++) {
274: if (batchedExceptionGenerated_[i]) {
275: updateCounts[i] = -3;
276: }
277: }
278: if (accumulatedExceptions == null) {
279: try {
280: endReadChain();
281: } catch (SqlException e) {
282: accumulatedExceptions = e;
283: }
284: }
285: if (accumulatedExceptions != null) {
286: BatchUpdateException bue = new BatchUpdateException(
287: logWriter_, new ClientMessageId(
288: SQLState.BATCH_NON_ATOMIC_FAILURE),
289: updateCounts);
290: bue.setNextException(accumulatedExceptions
291: .getSQLException());
292: throw bue;
293: }
294: }
295: }
|