db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From kmars...@apache.org
Subject svn commit: rev 55942 - incubator/derby/code/trunk/java/drda/org/apache/derby/impl/drda
Date Fri, 29 Oct 2004 04:56:30 GMT
Author: kmarsden
Date: Thu Oct 28 21:56:29 2004
New Revision: 55942

Modified:
   incubator/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DDMReader.java
   incubator/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DDMWriter.java
   incubator/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java
   incubator/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DssConstants.java
   incubator/derby/code/trunk/java/drda/org/apache/derby/impl/drda/TestProto.java
Log:
Derby35 - Fix dss chaining problems for network server.
Checked in for Army Brown army@golux.com


Modified: incubator/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DDMReader.java
==============================================================================
--- incubator/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DDMReader.java	(original)
+++ incubator/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DDMReader.java	Thu Oct
28 21:56:29 2004
@@ -1368,6 +1368,8 @@
 	protected void clearBuffer() throws DRDAProtocolException
 	{
 		skipBytes(java.lang.Math.min(dssLength, count - pos));
+    	dssIsChainedWithSameID = false;
+    	dssIsChainedWithDiffID = false;
 	}
 
 	/**
@@ -1751,4 +1753,20 @@
 	   s += indent + "Reader buffer length = " + buffer.length + "\n";
 	   return s;
 	}
+
+	/**
+	 * Return chaining bit for current DSS.
+	 */
+	protected byte getCurrChainState() {
+
+		if (!dssIsChainedWithSameID && !dssIsChainedWithDiffID)
+			return DssConstants.DSS_NOCHAIN;
+
+		if (dssIsChainedWithSameID)
+			return DssConstants.DSSCHAIN_SAME_ID;
+
+		return DssConstants.DSSCHAIN;
+
+	}
+
 }

Modified: incubator/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DDMWriter.java
==============================================================================
--- incubator/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DDMWriter.java	(original)
+++ incubator/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DDMWriter.java	Thu Oct
28 21:56:29 2004
@@ -55,8 +55,6 @@
 	// top of the stack
 	private int top;
 
-	private boolean simpleDssFinalize = false;
-
 	// CCSID manager for translation of strings in the protocol to EBCDIC
 	private CcsidManager ccsidManager;
 
@@ -80,14 +78,29 @@
 	// trace object of the associated session
 	private DssTrace dssTrace;
 
+	// Location within the "bytes" array of the start of the header
+	// of the DSS most recently written to the buffer.
+	private int prevHdrLocation;
+
+	// Correlation id of the last DSS that was written to buffer.
+	private int previousCorrId;
 
+	// Chaining bit of the last DSS that was written to buffer.
+	private byte previousChainByte;
 
+	// Whether or not the current DSS is a continuation DSS.
+	private boolean isContinuationDss;
+	
 	// Constructors
 	DDMWriter (int minSize, CcsidManager ccsidManager, DRDAConnThread agent, DssTrace dssTrace)
 	{
 		this.bytes = new byte[minSize];
 		this.ccsidManager = ccsidManager;
 		this.agent = agent;
+		this.prevHdrLocation = -1;
+		this.previousCorrId = DssConstants.CORRELATION_ID_UNKNOWN;
+		this.previousChainByte = DssConstants.DSS_NOCHAIN;
+		this.isContinuationDss = false;
 		reset(dssTrace);
 	}
 
@@ -96,6 +109,10 @@
 		this.bytes = new byte[DEFAULT_BUFFER_SIZE];
 		this.ccsidManager = ccsidManager;
 		this.agent = agent;
+		this.prevHdrLocation = -1;
+		this.previousCorrId = DssConstants.CORRELATION_ID_UNKNOWN;
+		this.previousChainByte = DssConstants.DSS_NOCHAIN;
+		this.isContinuationDss = false;
 		reset(dssTrace);
 	}
 
@@ -127,53 +144,123 @@
 	 */
 	protected void createDssReply()
 	{
-		// finish off previous DSS
-    	if (offset != 0)
-    		finalizePreviousChainedDss(false);
-		beginDss(DssConstants.DSSFMT_RPYDSS, nextCorrelationID++);
-		simpleDssFinalize = false;
+		beginDss(DssConstants.DSSFMT_RPYDSS, true);
 	}
 
 	/**
 	 * Create DSS request object
+	 * NOTE: This is _ONLY_ used for testing the protocol
+	 * (via the TestProto.java file in this package)!
+	 * We should never create a DSS request in normal
+	 * DRDA processing (we should only create DSS replies
+	 * and DSS objects).
 	 */
-	protected void createDssRequest(int corrID)
+	protected void createDssRequest()
 	{
-		// finish off previous DSS
-    	if (offset != 0)
-    		finalizePreviousChainedDss((correlationID == corrID));
-		beginDss(DssConstants.DSSFMT_RQSDSS, corrID);
-		simpleDssFinalize = false;
+		beginDss(DssConstants.DSSFMT_RQSDSS, true);
 	}
+
 	/**
 	 * Create DSS data object
 	 */
-	protected void createDssObject(boolean reuseCorrID)
+	protected void createDssObject()
 	{
-		// finish off previous DSS - objects are always part of a previous
-		// DSS reply - so correlation id should be the same
-    	if (offset != 0)
-    		finalizePreviousChainedDss (reuseCorrID);
-		beginDss(DssConstants.DSSFMT_OBJDSS, (reuseCorrID ? correlationID : nextCorrelationID++));
-		simpleDssFinalize = false;
+		beginDss(DssConstants.DSSFMT_OBJDSS, true);
 	}
+
 	/**
-	 * Create DSS data object
+	 * Mark the DSS that we're currently writing as
+	 * a continued DSS, which is done by setting
+	 * the high-order bit to "1", per DDM spec.
+	 * This means:
+	 *
+	 *	1. One or more continuation DSSes will immediately
+	 * 		follow the current (continued) DSS.
+	 *	2. All continuation DSSes will have a 2-byte
+	 * 		continuation header, followed by data; in
+	 * 		other words, chaining state, correlation
+	 *		id, dss format info, and code point will
+	 * 		NOT be included.  All of that info is 
+	 * 		present ONLY in the FIRST DSS in the
+	 *		list of continued DSSes.
+	 *
+	 *	NOTE: A DSS can be a "continuation" DSS _and_
+	 * 	a "continued" DSS at the same time.  However,
+	 * 	the FIRST DSS to be continued canNOT be
+	 *	a continuation DSS.
+	 */
+	private void markDssAsContinued(boolean forLob)
+	{
+
+		if (!forLob) {
+		// continuation bit defaults to '1' for lobs, so
+		// we only have to switch it if we're not writing
+		// lobs.
+			bytes[dssLengthLocation] |= 0x80;
+		}
+
+		// We need to set the chaining state, but ONLY
+		// IF this is the FIRST DSS in the continuation
+		// list (only the first one has chaining state
+		// in it's header; the others do not).
+		if (!isContinuationDss)
+			endDss(!forLob);
+
+	}
+
+	/**
+	 * End DSS header by writing the length in the length location
+	 * and setting the chain bit.  Unlike the other two endDss
+	 * methods, this one overrides the default chaining byte
+	 * (which is set in beginDss) with the chaining byte that
+	 * is passed in.  NOTE: This method is only used in
+	 * association with createDssRequest, and thus is for
+	 * TESTING purposes only (via TestProto.java).  No calls
+	 * should be made to this method in normal DRDA processing
+	 * (because for normal processing, chaining must be
+	 * determined automatically based on DSS requests).
+	 */
+	protected void endDss(byte chainByte)
+	{
+
+		// Do regular endDss processing.
+		endDss(true);
+
+		// Now override default chain state.
+		bytes[dssLengthLocation + 3] &= 0x0F;	// Zero out default
+		bytes[dssLengthLocation + 3] |= chainByte;
+		previousChainByte = chainByte;
+
+	}
+
+	/**
+	 * End DSS header by writing the length in the length location
+	 * and setting the chain bit.
 	 */
-	protected void createDssObject()
-	{
-		createDssObject(true);
+	protected void endDss() {
+		endDss(true);
 	}
 
 	/**
 	 * End DSS header by writing the length in the length location
-	 *
+	 * and setting the chain bit.
 	 */
-	protected void endDss ()
+	private void endDss (boolean finalizeLength)
 	{
-		int val = offset - dssLengthLocation;
-		bytes[dssLengthLocation] = (byte) ((val >>> 8) & 0xff);
-		bytes[dssLengthLocation + 1] = (byte) (val & 0xff);
+
+		if (finalizeLength)
+			finalizeDssLength();
+
+		if (isContinuationDss) {
+		// no chaining information for this DSS; so we're done.
+			isContinuationDss = false;
+			return;
+		}
+
+		previousCorrId = correlationID;
+		prevHdrLocation = dssLengthLocation;
+		previousChainByte = DssConstants.DSSCHAIN_SAME_ID;
+
 	}
 
 	/**
@@ -236,6 +323,7 @@
 		top = 0;
 		dssLengthLocation = 0;
 		correlationID = DssConstants.CORRELATION_ID_UNKNOWN;
+		nextCorrelationID = 1;
 		isDRDAProtocol = true;
 	}
 
@@ -536,21 +624,21 @@
 	}
 
 
-	protected int  writeScalarStream (boolean chained,
-									  boolean chainedWithSameCorrelator,
+	protected int  writeScalarStream (boolean chainedWithSameCorrelator,
 									  int codePoint,
 									  int length,
 									  java.io.InputStream in,
 									  boolean writeNullByte) 
 		throws DRDAProtocolException
 	{
+
+		// Stream equivalent of "beginDss"...
 		int leftToRead = length;
-		int bytesToRead = prepScalarStream (chained,
-											chainedWithSameCorrelator,
+		int bytesToRead = prepScalarStream (chainedWithSameCorrelator,
 											codePoint,
 											writeNullByte,
 											leftToRead);
-		
+
 		if (length == 0)
 			return 0;
 
@@ -577,7 +665,7 @@
 					leftToRead -= bytesRead;
 				}
 			} while (bytesToRead > 0);
-			
+
 			bytesToRead = flushScalarStreamSegment (leftToRead, bytesToRead);
 		} while (leftToRead > 0);
 		
@@ -595,60 +683,35 @@
 		return totalBytesRead;
 	}
 	
-	
-	private void beginDss (boolean dssHasSameCorrelator,
-						   boolean chainedToNextStructure,
-						   boolean nextHasSameCorrelator,
-						   int dssType,
-						   int corrId,
-						   boolean simpleFinalizeBuildingNextDss)
-  {
-	  if (doesRequestContainData()) {
-		  if (simpleDssFinalize)
-		  {
-			  finalizeDssLength();
-
-		  }
-		  else
-			  finalizePreviousChainedDss (dssHasSameCorrelator);
-	  }
-
-	  ensureLength (6);
-
-	  // save the length position and skip
-	  // note: the length position is saved so it can be updated
-	  // with a different value later.
-	  dssLengthLocation = offset;
-	  // always turn on chaining flags... this is helpful for lobs...
-	  // these bytes will get rest if dss lengths are finalized.
-	  bytes[offset] = (byte) 0xFF;
-	  bytes[offset + 1] = (byte) 0xFF;
-
-	  // insert the manditory 0xD0 and the dssType
-	  bytes[offset + 2] = (byte) 0xD0;
-
-    if (chainedToNextStructure) {
-      dssType |= DssConstants.GDSCHAIN;
-      if (nextHasSameCorrelator)
-        dssType |= DssConstants.GDSCHAIN_SAME_ID;
-    }
-    bytes[offset + 3] = (byte) (dssType & 0xff);
+	/**
+	 * Begins a DSS stream (for writing LOB data).
+	 */
+	private void beginDss (boolean chainedToNextStructure,
+						   int dssType)
+	{
+		beginDss(dssType, false);	// false => don't ensure length.
 
-    // write the request correlation id
-    // use method that writes a short !!!
-    bytes[offset + 4] = (byte) ((corrId >>> 8) & 0xff);
-    bytes[offset + 5] = (byte) (corrId & 0xff);
-	offset +=6;
-    simpleDssFinalize = simpleFinalizeBuildingNextDss;
-  }
+		// always turn on continuation flags... this is helpful for lobs...
+		// these bytes will get rest if dss lengths are finalized.
+  		bytes[dssLengthLocation] = (byte) 0xFF;
+  		bytes[dssLengthLocation + 1] = (byte) 0xFF;
+
+		// Set whether or not this DSS should be chained to
+		// the next one.  If it's chained, it has to be chained
+		// with same id (that's the nature of EXTDTA chaining).
+		if (chainedToNextStructure) {
+			dssType |= DssConstants.GDSCHAIN_SAME_ID;
+		}
+
+		bytes[dssLengthLocation + 3] = (byte) (dssType & 0xff);
+	}
 
 
   // prepScalarStream does the following prep for writing stream data:
   // 1.  Flushes an existing DSS segment, if necessary
   // 2.  Determines if extended length bytes are needed
   // 3.  Creates a new DSS/DDM header and a null byte indicator, if applicable
-  protected int prepScalarStream  (boolean chained,
-                                   boolean chainedWithSameCorrelator,
+  protected int prepScalarStream  (boolean chainedWithSameCorrelator,
                                    int codePoint,
                                    boolean writeNullByte,
                                    int leftToRead) throws DRDAProtocolException
@@ -663,10 +726,8 @@
     // flush the existing DSS segment if this stream will not fit in the send buffer
     if (10 + extendedLengthByteCount + nullIndicatorSize + leftToRead + offset > DssConstants.MAX_DSS_LENGTH)
{
       try {
-        if (simpleDssFinalize)
-          finalizeDssLength();
-        else
-          finalizePreviousChainedDss (true);
+	    // The existing DSS segment was finalized by endDss; all
+	    // we have to do is send it across the wire.
         sendBytes(agent.getOutputStream());
       }
       catch (java.io.IOException e) {
@@ -677,12 +738,7 @@
     }
 
     // buildStreamDss should not call ensure length.
-    beginDss (true,
-			  chained,
-			  chainedWithSameCorrelator,
-			  DssConstants.GDSFMT_OBJDSS,
-			  correlationID,
-			  true);
+	beginDss(chainedWithSameCorrelator, DssConstants.GDSFMT_OBJDSS);
 
     if (extendedLengthByteCount > 0) {
       // method should never ensure length
@@ -728,31 +784,48 @@
 	protected int flushScalarStreamSegment (int leftToRead,
 											int bytesToRead)
 		throws DRDAProtocolException
-  {
-	  int newBytesToRead = bytesToRead;
+	{
+		int newBytesToRead = bytesToRead;
 
-	  // either at end of data, end of dss segment, or both.
-	  if (leftToRead != 0) {
-		  // 32k segment filled and not at end of data.
-		  if ((Math.min (2 + leftToRead, 32767)) > (bytes.length - offset)) {
-        try {
-          sendBytes (agent.getOutputStream());
-        }
-        catch (java.io.IOException ioe) {
-			agent.markCommunicationsFailure ("DDMWriter.flushScalarStreamSegment()",
+		// either at end of data, end of dss segment, or both.
+		if (leftToRead != 0) {
+		// 32k segment filled and not at end of data.
+
+			if ((Math.min (2 + leftToRead, 32767)) > (bytes.length - offset)) {
+				try {
+				// Mark current DSS as continued, set its chaining state,
+				// then send the data across.
+					markDssAsContinued(true); 	// true => for lobs
+					sendBytes (agent.getOutputStream());
+				}
+				catch (java.io.IOException ioe) {
+					agent.markCommunicationsFailure ("DDMWriter.flushScalarStreamSegment()",
                                                "",
                                                ioe.getMessage(),
                                                "*");
-        }
-      }
-      dssLengthLocation = offset;
-      bytes[offset++] = (byte) (0xff);
-      bytes[offset++] = (byte) (0xff);
-      newBytesToRead = Math.min (leftToRead,32765);
-    }
+				}
+			}
+			else {
+			// DSS is full, but we still have space in the buffer.  So
+			// end the DSS, then start the next DSS right after it.
+				endDss(false);		// false => don't finalize length.
+			}
 
-    return newBytesToRead;
-  }
+			// Prepare a DSS continuation header for next DSS.
+			dssLengthLocation = offset;
+			bytes[offset++] = (byte) (0xff);
+			bytes[offset++] = (byte) (0xff);
+			newBytesToRead = Math.min (leftToRead,32765);
+			isContinuationDss = true;
+  		}
+		else {
+		// we're done writing the data, so end the DSS.
+			endDss();
+		}
+
+		return newBytesToRead;
+
+	}
 
   // the offset must not be updated when an error is encountered
   // note valid data may be overwritten
@@ -1193,12 +1266,20 @@
 	 */
 	protected void flush () throws java.io.IOException
 	{
-		OutputStream socketOutputStream = agent.getOutputStream();
+		flush(agent.getOutputStream());
+	}
+
+	/**
+	 * Flush buffer to specified stream
+	 *
+	 * @param socketOutputStream
+	 *
+	 * @exception IOException
+	 */
+	protected void flush(OutputStream socketOutputStream)
+		throws java.io.IOException
+	{
 		try {
-			if (isDRDAProtocol)
-			{
-				finalizeDssLength();
-			}
 			socketOutputStream.write (bytes, 0, offset);
 			socketOutputStream.flush();
 		}
@@ -1215,18 +1296,6 @@
 			reset(dssTrace);
 		}
 	}
-	/**
-	 * Flush buffer to specified stream
-	 *
-	 * @param socketOutputStream
-	 *
-	 * @exception IOException
-	 */
-	protected void flush(OutputStream os) throws java.io.IOException
-	{
-		os.write(bytes, 0, offset);
-		os.flush();
-	}
 
 	// private methods
 
@@ -1252,41 +1321,41 @@
 	 *			 - 4 - Communications DSS
 	 *			 - 5 - Request DSS where no reply is expected
 	 */
-	private void beginDss (int dssType, int corrID)
+	private void beginDss (int dssType, boolean ensureLen)
 	{
-		// save correlationID for use in error messages while processing
-		// this DSS
-		correlationID = corrID;
+
 		// save length position, the length will be written at the end
 		dssLengthLocation = offset;
 
-		ensureLength(6);
+		// Should this really only be for non-stream DSSes?
+		if (ensureLen)
+			ensureLength(6);
+
+		// Skip past length; we'll come back and set it later.
 		offset += 2;
 
 		// write gds info
 		bytes[offset] = (byte) 0xD0;
+
+		// Write DSS type, and default chain bit to be 
+		// DssConstants.DSSCHAIN_SAME_ID.  This default
+		// will be overridden by calls to "finalizeChain()"
+		// and/or calls to "beginDss(boolean, int)" for
+		// writing LOB data.
 		bytes[offset + 1] = (byte) dssType;
+		bytes[offset + 1] |= DssConstants.DSSCHAIN_SAME_ID;
+
+		// save correlationID for use in error messages while processing
+		// this DSS
+		correlationID = getCorrelationID();
 
-		// write the request correlation id
-		bytes[offset + 2] = (byte) ((corrID >>> 8) & 0xff);
-		bytes[offset + 3] = (byte) (corrID & 0xff);
+		// write the reply correlation id
+		bytes[offset + 2] = (byte) ((correlationID >>> 8) & 0xff);
+		bytes[offset + 3] = (byte) (correlationID & 0xff);
 		offset += 4;
 	}
 
 	/**
-	 * finish the DSS in the buffer by updating the length and chaining bits
-	 *
-	 * @param nextDssHasSameCorrelator - how to set chaining bits
-	 */
-  	private void finalizePreviousChainedDss (boolean nextDssHasSameCorrelator)
-	{
-		finalizeDssLength();
-		bytes[dssLengthLocation + 3] |= 0x40;
-		if (nextDssHasSameCorrelator)
-			bytes[dssLengthLocation + 3] |= 0x10;
-		
-	}
-	/**
      * Finish a DSS Layer A object.
 	 * The length of dss object will be calculated based on the difference between the
 	 * start of the dss, saved on the beginDss call, and the current
@@ -1616,6 +1685,7 @@
 
   private void sendBytes (java.io.OutputStream socketOutputStream) throws java.io.IOException
   {
+	resetChainState();
     try {
       socketOutputStream.write (bytes, 0, offset);
       socketOutputStream.flush();
@@ -1635,43 +1705,6 @@
   }
 
 
-private void buildStreamDssObject (boolean chainedToNextStructure,
-								   boolean nextHasSameCorrelator,
-								   int corrID)
-  {
-	int dssType =   DssConstants.GDSFMT_OBJDSS;
-    if (offset != 0) {
-        finalizePreviousChainedDss (true);
-	}
-
-    ensureLength (6);
-
-    // save the length position and skip
-    // note: the length position is saved so it can be updated
-    // with a different value later.
-    dssLengthLocation = offset;
-    // always turn on chaining flags... this is helpful for lobs...
-    // these bytes will get rest if dss lengths are finalized.
-    bytes[offset] = (byte) 0xFF;
-    bytes[offset + 1] = (byte) 0xFF;
-
-    // insert the manditory 0xD0 and the dssType
-    bytes[offset + 2] = (byte) 0xD0;
-    if (chainedToNextStructure) {
-      dssType |= DssConstants.GDSCHAIN;
-      if (nextHasSameCorrelator)
-        dssType |= DssConstants.GDSCHAIN_SAME_ID;
-    }
-    bytes[offset + 3] = (byte) (  dssType & 0xff);
-
-    // write the request correlation id
-    // use method that writes a short !!!
-    bytes[offset + 4] = (byte) ((corrID >>> 8) & 0xff);
-    bytes[offset + 5] = (byte) (corrID & 0xff);
-	offset += 6;
-	}
-
-
 	private static int min (int i, int j)
 	{
 		return (i < j) ? i : j;
@@ -1687,8 +1720,97 @@
 		return s;
 	}
 
-}
+	/**
+	 * Reset any chaining state that needs to be reset
+	 * at time of the send
+	 */
+	protected void resetChainState()
+	{
+		prevHdrLocation = -1;
+	}
+
+	/**
+	 * Looks at chaining info for previous DSS written, and use
+	 * that to figure out what the correlation id for the current
+	 * DSS should be.  Return that correlation id.
+	 */
+	private int getCorrelationID() {
 
+		int cId;
+		if (previousCorrId != DssConstants.CORRELATION_ID_UNKNOWN) {
+			if (previousChainByte == DssConstants.DSSCHAIN_SAME_ID)
+			// then we have to use the last correlation id we sent.
+				cId = previousCorrId;
+			else
+			// get correlation id as normal.
+				cId = nextCorrelationID++;
+		}
+		else {
+		// must be the case that this is the first DSS we're
+		// writing for this connection (because we haven't
+		// called "endDss" yet).  So, get the corr id as
+		// normal.
+			cId = nextCorrelationID++;
+		}
 
+		return cId;
+
+	}
 
+	/**
+	 * Finalize the current DSS chain and send it if
+	 * needed.
+	 *
+	 * Updates the chaining state of the most recently-written-
+	 * to-buffer DSS to correspond to the most recently-read-
+	 * from-client request.  If that chaining state indicates
+	 * we've reached the end of a chain, then we go ahead
+	 * and send the buffer across the wire.
+	 * @param socketOutputStream Output stream to which we're flushing.
+	 */
+	protected void finalizeChain(byte currChainByte,
+		OutputStream socketOutputStream) throws DRDAProtocolException
+	{
+
+		// Go back to previous DSS and override the default
+		// chain state (WITH_SAME_ID) with whatever the last
+		// request dictates.
+
+		if (prevHdrLocation != -1) {
+		// Note: == -1 => the previous DSS was already sent; this
+		// should only happen in cases where the buffer filled up
+		// and we had to send it (which means we were probably
+		// writing EXTDTA).  In such cases, proper chaining
+		// should already have been handled @ time of send.
+			bytes[prevHdrLocation + 3] &= 0x0F;	// Zero out old chain value.
+			bytes[prevHdrLocation + 3] |= currChainByte;
+		}
+
+		// previousChainByte needs to match what we just did.
+		previousChainByte = currChainByte;
+
+		if (currChainByte != DssConstants.DSS_NOCHAIN)
+		// then we're still inside a chain, so don't send.
+			return;
+
+		// Else, we just ended the chain, so send it across.
+
+		if ((SanityManager.DEBUG) && (agent != null))
+			agent.trace("Sending data");
+
+		resetChainState();
+		if (offset != 0) {
+			try {
+				flush(socketOutputStream);
+			} catch (java.io.IOException e) {
+				agent.markCommunicationsFailure(
+					"DDMWriter.finalizeChain()",
+					"OutputStream.flush()",
+					e.getMessage(),"*");
+			}
+		}
+
+	}
+
+}
 

Modified: incubator/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java
==============================================================================
--- incubator/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java	(original)
+++ incubator/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DRDAConnThread.java	Thu
Oct 28 21:56:29 2004
@@ -572,10 +572,8 @@
 								writeNullSQLCARDobject();
 							}
 							// Send any warnings if JCC can handle them
-							checkWarning(null, null, stmt.getResultSet(), true, 0, false, sendWarningsOnCNTQRY);
+							checkWarning(null, null, stmt.getResultSet(), 0, false, sendWarningsOnCNTQRY);
 						}
-						send();
-
 					}
 					catch(SQLException e)
 					{
@@ -595,12 +593,12 @@
  										trace("Warning: Error closing statement");
 								}
 								writeABNUOWRM();
-								writeSQLCARD(true,e,CodePoint.SVRCOD_ERROR,0,0);
+								writeSQLCARD(e,CodePoint.SVRCOD_ERROR,0,0);
 							}
 						}
 						else 
 						{
-							writeSQLCARDs(e, false, 0);
+							writeSQLCARDs(e, 0);
 						}
 						errorInChain(e);
 					}
@@ -618,18 +616,17 @@
 						// builtin method to check(expensive)
 						// For now we will assume that every execute immediate
 						// does an update (that is the most conservative thing)
-						boolean reuseCorrID = false;
 						if (database.RDBUPDRM_sent == false)
 						{
 							writeRDBUPDRM();
-							reuseCorrID = true;
 						}
 
 						// we need to set update count in SQLCARD
-						checkWarning(null, database.getDefaultStatement().getStatement(), null, reuseCorrID,
updateCount, true, true);
+						checkWarning(null, database.getDefaultStatement().getStatement(),
+							null, updateCount, true, true);
 					} catch (SQLException e)
 					{
-						writeSQLCARDs(e, false, 0);
+						writeSQLCARDs(e, 0);
 						errorInChain(e);
 					}
 					break;
@@ -638,21 +635,15 @@
 					try {
 						if (parseEXCSQLSET())
 						// all went well.
-							writeSQLCARDs(null,true,0);
-						writer.endDss();
-						send();
+							writeSQLCARDs(null,0);
 					}
 					catch (SQLWarning w)
 					{
-						writeSQLCARD(true, w, CodePoint.SVRCOD_WARNING, 0, 0);
-						writer.endDss();
-						send();
+						writeSQLCARD(w, CodePoint.SVRCOD_WARNING, 0, 0);
 					}
 					catch (SQLException e)
 					{
-						writeSQLCARDs(e,false,0);
-						writer.endDss();
-						send();
+						writeSQLCARDs(e, 0);
 						errorInChain(e);
 					}
 					break;
@@ -668,11 +659,11 @@
 										 (sqldaType ==  CodePoint.TYPSQLDA_LIGHT_OUTPUT),
 										 database.getConnection().getWarnings());
 						else
-							checkWarning(database.getConnection(), null, null, false, 0, true, true);
+							checkWarning(database.getConnection(), null, null, 0, true, true);
 
 					} catch (SQLException e)
 					{
-						writeSQLCARDs(e, false, 0, true);
+						writeSQLCARDs(e, 0, true);
 						PRPSQLSTTfailed = true;
 						errorInChain(e);
 					}
@@ -681,15 +672,11 @@
 					PreparedStatement ps = null;
 					try {
 						if (PRPSQLSTTfailed) {
-							reader.skipBytes();
 							// read the command objects
 							// for ps with parameter
-							// Skip parameters too
-							if (reader.isChainedWithSameID())
-							{
-								correlationID = reader.readDssHeader();
-								reader.skipDss();
-							}
+							// Skip objects/parameters
+							skipRemainder(true);
+
 							// If we failed to prepare, then we fail
 							// to open, which  means OPNQFLRM.
 							writeOPNQFLRM(null);
@@ -703,7 +690,7 @@
 							ps.clearWarnings();
 							stmt.execute();
 							writeOPNQRYRM(false, stmt);
-							checkWarning(null, ps, null, true, 0, false, true);
+							checkWarning(null, ps, null, 0, false, true);
 
 							writeQRYDSC(stmt, false);
 							// We could send QRYDTA here if there's no LOB data
@@ -729,7 +716,6 @@
 						catch (SQLException pse) {}
 						errorInChain(e);
 					}
-					send();
 					break;
 				case CodePoint.RDBCMM:
 					try
@@ -741,7 +727,7 @@
 							database.getConnection().clearWarnings();
 							database.commit();
 							writeENDUOWRM(COMMIT);
-							checkWarning(database.getConnection(), null, null, true, 0, true, true);
+							checkWarning(database.getConnection(), null, null, 0, true, true);
 						}
 						// we only want to write one of these per transaction
 						// so set to false in preparation for next command
@@ -751,7 +737,7 @@
 					{
 						// Even in case of error, we have to write the ENDUOWRM.
 						writeENDUOWRM(COMMIT);
-						writeSQLCARDs(e, true, 0);
+						writeSQLCARDs(e, 0);
 						errorInChain(e);
 					}
 					break;
@@ -763,7 +749,7 @@
 						database.getConnection().clearWarnings();
 						database.rollback();
 						writeENDUOWRM(ROLLBACK);
-						checkWarning(database.getConnection(), null, null, true, 0, true, true);
+						checkWarning(database.getConnection(), null, null, 0, true, true);
 						// we only want to write one of these per transaction
 						// so set to false in preparation for next command
 						database.RDBUPDRM_sent = false;
@@ -772,7 +758,7 @@
 					{
 						// Even in case of error, we have to write the ENDUOWRM.
 						writeENDUOWRM(ROLLBACK);
-						writeSQLCARDs(e, true, 0);
+						writeSQLCARDs(e, 0);
 						errorInChain(e);
 					}
 					break;
@@ -780,11 +766,11 @@
 					try{
 						stmt = parseCLSQRY();
 						stmt.rsClose();
-						writeSQLCARDs(null, false, 0);
+						writeSQLCARDs(null, 0);
 					}
 					catch (SQLException e)
 					{
-						writeSQLCARDs(e, false, 0);
+						writeSQLCARDs(e, 0);
 						errorInChain(e);
 					}
 					break;
@@ -797,24 +783,25 @@
 				 */
 				case CodePoint.BGNBND:
 					reader.skipBytes();
-					writeSQLCARDs(null, false, 0);
+					writeSQLCARDs(null, 0);
 					break;
 				case CodePoint.BNDSQLSTT:
 					reader.skipBytes();
 					parseSQLSTTDss();
-					writeSQLCARDs(null, false, 0);
+					writeSQLCARDs(null, 0);
 					break;
 				case CodePoint.SQLSTTVRB:
+					// optional
 					reader.skipBytes();
 					break;
 				case CodePoint.ENDBND:
 					reader.skipBytes();
-					writeSQLCARDs(null, false, 0);
+					writeSQLCARDs(null, 0);
 					break;
 				case CodePoint.DSCSQLSTT:
 					if (PRPSQLSTTfailed) {
 						reader.skipBytes();
-						writeSQLCARDs(null, false, 0);
+						writeSQLCARDs(null, 0);
 						break;
 					}
 					try {
@@ -832,18 +819,12 @@
 						}
 						errorInChain(e);
 					}
-					send();
 					break;
 				case CodePoint.EXCSQLSTT:
 					if (PRPSQLSTTfailed) {
-						reader.skipBytes();
 						// Skip parameters too if they are chained Beetle 4867
-						while(reader.isChainedWithSameID())
-						{
-							correlationID = reader.readDssHeader();
-							reader.skipDss();
-						}
-						writeSQLCARDs(null, false, 0);
+						skipRemainder(true);
+						writeSQLCARDs(null, 0);
 						break;
 					}
 					try {
@@ -858,16 +839,22 @@
 						{
 							server.consoleExceptionPrint(e);
 						}
-						writeSQLCARDs(e, false, 0);
+						writeSQLCARDs(e, 0);
 						errorInChain(e);
 					}
 					break;
 				default:
 					codePointNotSupported(codePoint);
 			}
+
+			// Set the correct chaining bits for whatever
+			// reply DSS(es) we just wrote.  If we've reached
+			// the end of the chain, this method will send
+			// the DSS(es) across.
+			finalizeChain();
+
 		}
 		while (reader.isChainedWithSameID() || reader.isChainedWithDiffID());
-		send();
 	}
 
 	/**
@@ -890,11 +877,7 @@
 		if (reader.terminateChainOnErr() && (getExceptionSeverity(e) > CodePoint.SVRCOD_ERROR))
 		{
 			if (SanityManager.DEBUG)  trace("terminating the chain on error...");
-			while(reader.isChainedWithSameID() || reader.isChainedWithDiffID())
-			{
-				correlationID = reader.readDssHeader();
-				reader.skipDss();
-			}
+			skipRemainder(false);
 		}
 	}
 
@@ -935,7 +918,7 @@
 		appRequester = new AppRequester();
 		parseEXCSAT();
 		writeEXCSATRD();
-		send();
+		finalizeChain();
 
 		//we may have to do the access security more than once if we don't
 		//provide the requested security mechanism or we run into errors
@@ -981,7 +964,6 @@
 		//at this point if the security check failed, we're done, the session failed
 		if (securityCheckCode != 0)
 		{
-			send();
 			return false;
 		}
 
@@ -1000,30 +982,46 @@
 				|| failureType == CodePoint.RDBATHRM)
 			{
 				writeRDBfailure(failureType);
-				writeSQLCARD(true,databaseAccessException,
+				writeSQLCARD(databaseAccessException,
 					CodePoint.SVRCOD_ERROR,0,0);
 			}
 			else
 			{
 				writeRDBfailure(CodePoint.RDBAFLRM);
+
 				// RDBAFLRM requires TYPDEFNAM and TYPDEFOVR
+				writer.createDssObject();
 				writer.writeScalarString(CodePoint.TYPDEFNAM,
 										 CodePoint.TYPDEFNAM_QTDSQLASC);
 				writeTYPDEFOVR();
-				writeSQLCARD(true,databaseAccessException,
+				writer.endDss();
+
+				// Finally, per DDM spec, "an SQLCARD always follows
+				// the RDBAFLRM".
+				writeSQLCARD(databaseAccessException,
 							 CodePoint.SVRCOD_ERROR,0,0);
 			}
 
-			send();
+			// Ignore anything that was chained to the ACCRDB.
+			skipRemainder(false);
+
+			// Finalize chain state for whatever we wrote in
+			// response to ACCRDB.
+			finalizeChain();
 			return false;
 		}
 		else if (database.accessCount > 1 )	// already in conversation with database
 		{
 			writeRDBfailure(CodePoint.RDBACCRM);
-			send();
+
+			// Ignore anything that was chained to the ACCRDB.
+			skipRemainder(false);
+
+			// Finalize chain state for RDBACCRM
+			finalizeChain();
 			return false;
 		}
-		else // everything is fine
+		else // everything is fine 
 			writeACCRDBRM(svrcod);
 
 		// compare this application requester with previously stored
@@ -2131,7 +2129,7 @@
 		if (stmt.rsIsClosed())
 		{
 			writeQRYNOPRM(CodePoint.SVRCOD_ERROR);
-			skipRemainder();
+			skipRemainder(true);
 			return null;
 		}
 		stmt.setQueryOptions(blksize,qryrelscr,qryrownbr,qryrfrtbl,nbrrow,maxblkext,
@@ -2145,12 +2143,17 @@
 	/**
 	 * Skip remainder of current DSS and all chained DSS'es
 	 *
+	 * @param onlySkipSameIds True if we _only_ want to skip DSS'es
+	 *   that are chained with the SAME id as the current DSS.
+	 *   False means skip ALL chained DSSes, whether they're
+	 *   chained with same or different ids.
 	 * @exception DRDAProtocolException
 	 */
-	private void skipRemainder() throws DRDAProtocolException
+	private void skipRemainder(boolean onlySkipSameIds) throws DRDAProtocolException
 	{
 		reader.skipDss();
-		while (reader.isChainedWithSameID())
+		while (reader.isChainedWithSameID() ||
+			(!onlySkipSameIds && reader.isChainedWithDiffID()))
 		{
 			reader.readDssHeader();
 			reader.skipDss();
@@ -2390,7 +2393,7 @@
 	 * 
 	 * @exception DRDAProtocolException
 	 */
-	private void writeACCSECRD(int securityCheckCode) 
+	private void writeACCSECRD(int securityCheckCode)
 		throws DRDAProtocolException
 	{
 		writer.createDssReply();
@@ -2415,14 +2418,14 @@
 		}
     	writer.endDdmAndDss ();
 
-		/* The chaining status in reader is for the latest request DSS ACCSEC.
-		 * There's a difference between JCC and CCC here.  CCC chains ACCSEC, SECCHK,
-		 * and ACCRDB together, whereas JCC sends ACCSEC separately.  DRDA spec
-		 * requires that if requests are chained, replies must be chained.  When we
-		 * call "send", we terminate the chain.  So can't do it if ACCSEC is chained.
-		 */
-		if (! (reader.isChainedWithSameID() || reader.isChainedWithDiffID()))
-			send();
+		if (securityCheckCode != 0) {
+		// then we have an error and so can ignore the rest of the
+		// DSS request chain.
+			skipRemainder(false);
+		}
+
+		finalizeChain();
+
 	}
 	/**
 	 * Parse security check
@@ -2592,8 +2595,16 @@
 		writer.startDdm(CodePoint.SECCHKRM);
 		writer.writeScalar2Bytes(CodePoint.SVRCOD, svrcodFromSecchkcd(securityCheckCode));
 		writer.writeScalar1Byte(CodePoint.SECCHKCD, securityCheckCode);
-
     	writer.endDdmAndDss ();
+
+		if (securityCheckCode != 0) {
+		// then we have an error and are going to end up ignoring the rest
+		// of the DSS request chain.
+			skipRemainder(false);
+		}
+
+		finalizeChain();
+
 	}
 	/**
 	 * Calculate SVRCOD value from SECCHKCD
@@ -2840,7 +2851,7 @@
 								 CodePoint.TYPDEFNAM_QTDSQLASC);
 		writeTYPDEFOVR();
 		writer.endDdmAndDss ();
-		send();
+		finalizeChain();
 	}
 	
 	private void writeTYPDEFOVR() throws DRDAProtocolException
@@ -3439,7 +3450,7 @@
 			database.getConnection().clearWarnings();
 			CallableStatement cs = (CallableStatement) stmt.prepare(prepareString);
 		}
-		
+
 		stmt.ps.clearWarnings();
 
 		boolean hasResultSet = stmt.execute();
@@ -3501,7 +3512,7 @@
 			//indicate that we are going to return data
 			stmt.setQryrtndta(true);
 			if (! isProcedure)
-				checkWarning(null, ps, null, true, -1, true, true);
+				checkWarning(null, ps, null, -1, true, true);
 			if (rsNum == 0)
 				writeSQLRSLRD(stmt);
 			writeOPNQRYRM(true, stmt);
@@ -3520,21 +3531,14 @@
 		else  if (! sendSQLDTARD)
 		{
 			int updateCount = ps.getUpdateCount();
-			boolean reuseCorrID = false;			// RESOLVE:  We should send this but get protocol err if
-			// we do!!!
 			if (false && (database.RDBUPDRM_sent == false) &&
 				! isProcedure)
 			{
 				writeRDBUPDRM();
-				//following SQLCARD has to be in a continued DSS
-				reuseCorrID = true;
 			}
 
-
-			checkWarning(database.getConnection(), stmt.ps, null, false, updateCount, true, true);
+			checkWarning(database.getConnection(), stmt.ps, null, updateCount, true, true);
 		}
-		else
-			writer.endDss();
 
 		} while(hasResultSet && (++rsNum < numResults));
 		
@@ -3723,14 +3727,7 @@
 		} 
 		catch (SQLException se)
 		{
-			reader.skipDss();
-			while (reader.isChainedWithSameID() || 
-				   reader.isChainedWithDiffID())
-			{
-				correlationID = reader.readDssHeader();
-				reader.skipDss();
-				
-			}
+			skipRemainder(false);
 			throw se;
 		}
 	}
@@ -3924,7 +3921,7 @@
 				else
 					ps.setShort(i+1, paramVal);
 				break;
-		}
+			}
 			case  FdocaConstants.DRDA_TYPE_NINTEGER:
 			{
 				int paramVal = reader.readInt(getByteOrder());
@@ -4792,20 +4789,20 @@
 
 	}
 
-	private void writeSQLCARDs(SQLException e, boolean reuseCorrID, int updateCount)
+	private void writeSQLCARDs(SQLException e, int updateCount)
 									throws DRDAProtocolException
 	{
-		writeSQLCARDs(e, reuseCorrID, updateCount, false);
+		writeSQLCARDs(e, updateCount, false);
 	}
 
-	private void writeSQLCARDs(SQLException e, boolean reuseCorrID, int updateCount, boolean
sendSQLERRRM)
+	private void writeSQLCARDs(SQLException e, int updateCount, boolean sendSQLERRRM)
 									throws DRDAProtocolException
 	{
 
 		int severity = CodePoint.SVRCOD_INFO;
 		if (e == null)
 		{
-			writeSQLCARD(reuseCorrID, e,severity, updateCount, 0);
+			writeSQLCARD(e,severity, updateCount, 0);
 			return;
 		}
 
@@ -4817,9 +4814,8 @@
 		if (sendSQLERRRM || (severity > CodePoint.SVRCOD_ERROR))
 		{
 			writeSQLERRRM(severity);
-			reuseCorrID = true;
 		}
-		writeSQLCARD(reuseCorrID, e,severity, updateCount, 0);
+		writeSQLCARD(e,severity, updateCount, 0);
 	}
 
 	private int getSqlCode(int severity)
@@ -4832,10 +4828,10 @@
 			return -1;
 	}
 
-	private void writeSQLCARD(boolean reuseCorrID, SQLException e,int severity, 
+	private void writeSQLCARD(SQLException e,int severity, 
 		int updateCount, long rowCount ) throws DRDAProtocolException
 	{
-		writer.createDssObject(reuseCorrID);
+		writer.createDssObject();
 		writer.startDdm(CodePoint.SQLCARD);
 		writeSQLCAGRP(e, getSqlCode(severity), updateCount, rowCount);
 		writer.endDdmAndDss();
@@ -5388,7 +5384,7 @@
 				numElems = pmeta.getParameterCount();
 		}
 
-		writer.createDssObject(false);
+		writer.createDssObject();
 
 		// all went well we will just write a null SQLCA
 		writer.startDdm(CodePoint.SQLDARD);
@@ -5671,7 +5667,7 @@
 
 			if (stmt.getExtDtaObjects() != null)
 			{
-				writer.endDdm();
+				writer.endDdmAndDss();
 				writeEXTDTA(stmt);
 				getMoreData=false;
 				sentExtData = true;
@@ -5930,7 +5926,7 @@
 		{
 			// finish off query block and send
 			writer.endDdmAndDss();
-			send();
+			finalizeChain();
 			// read CNTQRY - not sure why JCC sends this
 			correlationID = reader.readDssHeader();
 			int codePoint = reader.readLengthAndCodePoint();
@@ -6331,25 +6327,6 @@
 		
 	}
 
-	
-	/**
-	 * Send data to application requester
-	 *
-	 * @exception DRDAProtocolException
-	 */
-	private void send() throws DRDAProtocolException
-	{
-		//check if there is data to send
-		if (writer.getOffset() == 0)
-			return;
-		if (SanityManager.DEBUG) trace("Sending data");
-		try {
-			writer.flush();
-		} catch (IOException ioe) {
-			markCommunicationsFailure("flush","","","");
-		}
-	}
-
   /**
    * Write Fdoca Value to client 
    * @param index     Index of column being returned
@@ -6732,7 +6709,7 @@
 				server.consoleExceptionPrintTrace(e);
 				reader.clearBuffer();
 				de.write(writer);
-				send();
+				finalizeChain();
 				closeSession();
 				close();
 			}
@@ -6778,7 +6755,7 @@
 		
 			reader.clearBuffer();
 			unExpDe.write(writer);
-			send();
+			finalizeChain();
 		}
 		catch (DRDAProtocolException nde) 
 		{
@@ -7014,8 +6991,7 @@
         if (o instanceof Blob) {
 			Blob b = (Blob) o;
 			long blobLength = b.length();
-			writer.writeScalarStream (chainFlag,
-									  chainedWithSameCorrelator,
+			writer.writeScalarStream (chainedWithSameCorrelator,
 									  CodePoint.EXTDTA,
 									  (int) Math.min(blobLength,
 													 Integer.MAX_VALUE),
@@ -7028,8 +7004,7 @@
 			long[] outlen = {-1};
 			ByteArrayInputStream  unicodeStream =
 				convertClobToUnicodeStream(c, outlen);
-			writer.writeScalarStream (chainFlag,
-									  chainedWithSameCorrelator,
+			writer.writeScalarStream (chainedWithSameCorrelator,
 									  CodePoint.EXTDTA,
 									  (int) Math.min(outlen[0],
 													 Integer.MAX_VALUE),		 
@@ -7038,8 +7013,7 @@
 		}
 		else if (o instanceof  byte[]) {
 			byte[] b = (byte []) o;
-			writer.writeScalarStream (chainFlag,
-									  chainedWithSameCorrelator,
+			writer.writeScalarStream (chainedWithSameCorrelator,
 									  CodePoint.EXTDTA,
 									  (int) b.length,
 									  new ByteArrayInputStream(b),
@@ -7095,7 +7069,6 @@
 	 * @param conn 		connection to check
 	 * @param stmt 		statement to check
 	 * @param rs 		result set to check
-	 * @param reuseCorrID 	whether send SQLCARD using previous correlation ID
 	 * @param updateCount 	update count to include in SQLCARD
 	 * @param alwaysSend 	whether always send SQLCARD regardless of
 	 *						the existance of warnings
@@ -7104,7 +7077,7 @@
 	 * @exception DRDAProtocolException
 	 */
 	private void checkWarning(Connection conn, Statement stmt, ResultSet rs,
-						  boolean reuseCorrID, int updateCount, boolean alwaysSend, boolean sendWarn)
+						  int updateCount, boolean alwaysSend, boolean sendWarn)
 		throws DRDAProtocolException, SQLException
 	{
 		// instead of writing a chain of sql warning, we send the first one, this is
@@ -7152,7 +7125,7 @@
 
 
 		if ((alwaysSend || reportWarning != null) && sendWarn)
-			writeSQLCARDs(reportWarning, reuseCorrID, updateCount);
+			writeSQLCARDs(reportWarning, updateCount);
 	}
 
 
@@ -7166,6 +7139,18 @@
 		s += "\n";
 		return s;
 	}
+
+	/**
+	 * Finalize the current DSS chain and send it if
+	 * needed.
+	 */
+	private void finalizeChain() throws DRDAProtocolException {
+
+		writer.finalizeChain(reader.getCurrChainState(), getOutputStream());
+		return;
+
+	}
+
 }
 
 

Modified: incubator/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DssConstants.java
==============================================================================
--- incubator/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DssConstants.java	(original)
+++ incubator/derby/code/trunk/java/drda/org/apache/derby/impl/drda/DssConstants.java	Thu
Oct 28 21:56:29 2004
@@ -29,13 +29,14 @@
   protected static final int DSS_ID = 0xD0;
 
   // DSS chaining bit.
+  protected static final int DSS_NOCHAIN = 0x00;
   protected static final int DSSCHAIN = 0x40;
 
   // DSS chaining bit for continuation on error
   protected static final int DSSCHAIN_ERROR_CONTINUE = 0x20;
 
   // DSS chaining bit where next DSS has same correlation ID.
-  protected static final int DSSCHAIN_SAME_ID = 0x10;
+  protected static final int DSSCHAIN_SAME_ID = 0x50;
 
   // DSS formatter for an OBJDSS.
   protected static final int DSSFMT_OBJDSS = 0x03;
@@ -59,7 +60,7 @@
   static final int GDSCHAIN = 0x40;
 
   // GDS chaining bits where next DSS has different correlation ID.
-  static final int GDSCHAIN_SAME_ID = 0x10;
+  static final int GDSCHAIN_SAME_ID = 0x50;
 
   // GDS formatter for an OBJDSS.
   static final int GDSFMT_OBJDSS = 0x03;

Modified: incubator/derby/code/trunk/java/drda/org/apache/derby/impl/drda/TestProto.java
==============================================================================
--- incubator/derby/code/trunk/java/drda/org/apache/derby/impl/drda/TestProto.java	(original)
+++ incubator/derby/code/trunk/java/drda/org/apache/derby/impl/drda/TestProto.java	Thu Oct
28 21:56:29 2004
@@ -310,7 +310,6 @@
 	private void processCommand()
 		throws IOException, DRDAProtocolException
 	{
-		int correlationId;
 		Integer icmd  = (Integer)commandTable.get(tkn.sval.toLowerCase(Locale.ENGLISH));
 		if (icmd == null)
 		{
@@ -330,8 +329,7 @@
 				processIncludeFile();
 				break;
 			case CREATE_DSS_REQUEST:
-				correlationId = getInt();
-				writer.createDssRequest(correlationId);
+				writer.createDssRequest();
 				break;
 			case CREATE_DSS_OBJECT:
 				writer.createDssObject();
@@ -340,7 +338,14 @@
 				writer.createDssReply();
 				break;
 			case END_DSS:
-				writer.endDss();
+				tkn.nextToken();
+				tkn.pushBack();
+				if ((tkn.sval != null) && tkn.sval.startsWith("0x"))
+				// use specified chaining.
+					writer.endDss((getBytes())[0]);
+				else
+				// use default chaining
+					writer.endDss();
 				break;
 			case END_DDM:
 				writer.endDdm();
@@ -448,7 +453,7 @@
 				checkIntOrCP(val);
 				break;
 			case FLUSH:
-				writer.flush(monitorOs);
+				writer.finalizeChain(reader.getCurrChainState(), monitorOs);
 				writer.reset(null);
 				break;
 			case DISPLAY:
@@ -622,7 +627,7 @@
 	 * in hex format or it can just be a string, in which case each char is
 	 * interpreted as  2 byte UNICODE
 	 *
-	 * @param byte array
+	 * @return byte array
 	 */
 	private byte []  getBytes() throws IOException
 	{

Mime
View raw message