⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ddmwriter.java

📁 derby database source code.good for you.
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
			// start of the segment and set the value of the 2-byte DSS			// continuation header, which needs to hold the length of			// this segment's data, together with the continuation flag			// if this is not the rightmost (passOne) segment.			//			// In general, each segment except the rightmost will contain			// 32765 bytes of data, plus the 2-byte header, and its			// continuation flag will be set, so the header value will			// be 0xFFFF. The rightmost segment will not have the			// continuation flag set, so its value may be anything from			// 0x0001 to 0x7FFF, depending on the amount of data in that			// segment.			//			// Note that the 0th (leftmost) segment also has a 2-byte			// DSS header, which needs to have its continuation flag set.			// This is done by resetting the "totalSize" variable below,			// at which point that variable no longer holds the total size			// of the object, but rather just the length of segment 0. The			// total size of the object was written using extended length			// bytes by the endDdm() method earlier.			//			// Additional information about this routine is available in the			// bug notes for DERBY-125:			// http://issues.apache.org/jira/browse/DERBY-125						// mark passOne to help with calculating the length of the final (first or			// rightmost) continuation header.			boolean passOne = true;			do {				// calculate chunk of data to shift				int dataToShift = bytesRequiringContDssHeader % 32765;				if (dataToShift == 0)					dataToShift = 32765;				int startOfCopyData = dataByte - dataToShift + 1;				System.arraycopy(bytes,startOfCopyData, bytes, 								 startOfCopyData + shiftSize, dataToShift);				dataByte -= dataToShift;				// calculate the value the value of the 2 byte continuation dss				// header which includes the length of itself.  On the first pass,				// if the length is 32767				// we do not want to set the continuation dss header flag.				int twoByteContDssHeader = dataToShift + 2;				if (passOne)					passOne = false;				else				{					if (twoByteContDssHeader == DssConstants.MAX_DSS_LENGTH)					twoByteContDssHeader = (twoByteContDssHeader |						DssConstants.CONTINUATION_BIT);				}				// insert the header's length bytes				bytes[dataByte + shiftSize - 1] = (byte)					((twoByteContDssHeader >>> 8) & 0xff);				bytes[dataByte + shiftSize] = (byte)					(twoByteContDssHeader & 0xff);				// adjust the bytesRequiringContDssHeader and the amount to shift for				// data in upstream headers.				bytesRequiringContDssHeader -= dataToShift;				shiftSize -= 2;				// shift and insert another header for more data.			}			while (bytesRequiringContDssHeader > 0);			// set the continuation dss header flag on for the first header			totalSize = (DssConstants.MAX_DSS_LENGTH |					DssConstants.CONTINUATION_BIT);		}		// insert the length bytes in the 6 byte dss header.		bytes[dssLengthLocation] = (byte) ((totalSize >>> 8) & 0xff);		bytes[dssLengthLocation + 1] = (byte) (totalSize & 0xff);	}	protected void writeExtendedLength(long size)	{		int numbytes = calculateExtendedLengthByteCount(size);		if (size > 0)			writeInt(0x8000 | numbytes);		else			writeInt(numbytes);	}	/**	 * Calculate extended length byte count which follows the DSS header	 * for extended DDM.	 *	 * @param ddmSize - size of DDM command	 * @return minimum number of extended length bytes needed. 0 indicates no	 * 	extended length needed.	 */	private int calculateExtendedLengthByteCount (long ddmSize)	{		if (ddmSize <= 0x7fff)			return 0;		// JCC does not support 2 at this time, so we always send		// at least 4		//		else if (ddmSize <= 0xffff)		//	return 2;		else if (ddmSize <= 0xffffffffL)			return 4;		else if (ddmSize <= 0xffffffffffffL)			return 6;		else if (ddmSize <= 0x7fffffffffffffffL)			return 8;		else			// shouldn't happen			// XXX - add sanity debug stuff here			return 0;	}	/**	 * Ensure that there is space in the buffer	 *	 * @param length space required	 */	private void ensureLength (int length)	{		length += offset;		if (length > bytes.length) {			if (SanityManager.DEBUG)			{				agent.trace("DANGER - Expensive expansion of  buffer");			}			byte newBytes[] = new byte[Math.max (bytes.length << 1, length)];			System.arraycopy (bytes, 0, newBytes, 0, offset);			bytes = newBytes;		}	}	/**	 * Write a Java <code>java.math.BigDecimal</code> to packed decimal bytes.	 *	 * @param b BigDecimal to write	 * @param precision Precision of decimal or numeric type	 * @return length written.	 *	 * @exception SQLException Thrown if # digits > 31	 */	private int bigDecimalToPackedDecimalBytes (java.math.BigDecimal b,												int precision, int scale)	throws SQLException	{		int declaredPrecision = precision;		int declaredScale = scale;		// packed decimal may only be up to 31 digits.		if (declaredPrecision > 31) // this is a bugcheck only !!!		{			clearDdm ();			throw new java.sql.SQLException ("Packed decimal may only be up to 31 digits!");		}		// get absolute unscaled value of the BigDecimal as a String.		String unscaledStr = b.unscaledValue().abs().toString();		// get precision of the BigDecimal.  	    int bigPrecision = unscaledStr.length();		if (bigPrecision > 31)		{			clearDdm ();  		    throw new SQLException ("The numeric literal \"" +                             b.toString() +                             "\" is not valid because its value is out of range.",                             "42820",                             -405);		}    	int bigScale = b.scale();  	    int bigWholeIntegerLength = bigPrecision - bigScale;	    if ( (bigWholeIntegerLength > 0) && (!unscaledStr.equals ("0")) ) {            // if whole integer part exists, check if overflow.            int declaredWholeIntegerLength = declaredPrecision - declaredScale;            if (bigWholeIntegerLength > declaredWholeIntegerLength)			{				clearDdm ();                throw new SQLException ("Overflow occurred during numeric data type conversion of \"" +                                       b.toString() +                                       "\".",                                       "22003",                                       -413);			}        }        // convert the unscaled value to a packed decimal bytes.        // get unicode '0' value.        int zeroBase = '0';        // start index in target packed decimal.        int packedIndex = declaredPrecision-1;        // start index in source big decimal.        int bigIndex;        if (bigScale >= declaredScale) {          // If target scale is less than source scale,          // discard excessive fraction.          // set start index in source big decimal to ignore excessive fraction.          bigIndex = bigPrecision-1-(bigScale-declaredScale);          if (bigIndex < 0) {            // all digits are discarded, so only process the sign nybble.            bytes[offset+(packedIndex+1)/2] =              (byte) ( (b.signum()>=0)?12:13 ); // sign nybble          }          else {            // process the last nybble together with the sign nybble.            bytes[offset+(packedIndex+1)/2] =              (byte) ( ( (unscaledStr.charAt(bigIndex)-zeroBase) << 4 ) + // last nybble                     ( (b.signum()>=0)?12:13 ) ); // sign nybble          }          packedIndex-=2;          bigIndex-=2;        }        else {          // If target scale is greater than source scale,          // pad the fraction with zero.          // set start index in source big decimal to pad fraction with zero.          bigIndex = declaredScale-bigScale-1;          // process the sign nybble.          bytes[offset+(packedIndex+1)/2] =            (byte) ( (b.signum()>=0)?12:13 ); // sign nybble          for (packedIndex-=2, bigIndex-=2; bigIndex>=0; packedIndex-=2, bigIndex-=2)            bytes[offset+(packedIndex+1)/2] = (byte) 0;          if (bigIndex == -1) {            bytes[offset+(packedIndex+1)/2] =              (byte) ( (unscaledStr.charAt(bigPrecision-1)-zeroBase) << 4 ); // high nybble            packedIndex-=2;            bigIndex = bigPrecision-3;          }          else {            bigIndex = bigPrecision-2;          }        }        // process the rest.        for (; bigIndex>=0; packedIndex-=2, bigIndex-=2) {          bytes[offset+(packedIndex+1)/2] =            (byte) ( ( (unscaledStr.charAt(bigIndex)-zeroBase) << 4 ) + // high nybble                   ( unscaledStr.charAt(bigIndex+1)-zeroBase ) ); // low nybble        }        // process the first nybble when there is one left.        if (bigIndex == -1) {          bytes[offset+(packedIndex+1)/2] =            (byte) (unscaledStr.charAt(0) - zeroBase);          packedIndex-=2;        }        // pad zero in front of the big decimal if necessary.        for (; packedIndex>=-1; packedIndex-=2)          bytes[offset+(packedIndex+1)/2] = (byte) 0;        return declaredPrecision/2 + 1;	}	/***	 * Prepend zeros to numeric string	 *	 * @param s string	 * @param precision - length of padded string 	 *	 * @return zero padded string	 */	public static String zeroPadString(String s, int precision)	{		if (s == null)			return s;		int slen = s.length();		if (precision == slen)			return s;		else if (precision > slen)		{			char[] ca  = new char[precision - slen];			Arrays.fill(ca,0,precision - slen,'0');			return new String(ca) + s;		}		else		{			// Shouldn't happen but just in case 			// truncate			return s.substring(0,precision);		}	}  private void sendBytes (java.io.OutputStream socketOutputStream) throws java.io.IOException  {	resetChainState();    try {      socketOutputStream.write (bytes, 0, offset);      socketOutputStream.flush();    }    finally {		if ((dssTrace != null) && dssTrace.isComBufferTraceOn()) {			dssTrace.writeComBufferData (bytes,			                               0,			                               offset,			                               DssTrace.TYPE_TRACE_SEND,			                               "Reply",			                               "flush",			                               5);      }      clearBuffer();    }  }	private static int min (int i, int j)	{		return (i < j) ? i : j;	}	protected String toDebugString(String indent)	{		String s = indent + "***** DDMWriter toDebugString ******\n";		int byteslen = 0;		if ( bytes != null)			byteslen = bytes.length;		s += indent + "byte array length  = " + bytes.length + "\n";		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(),"*");			}		}	}	/**	 * Takes note of the location of the most recently completed	 * DSS in the buffer, and then returns the current offset.	 * This method is used in conjunction with "clearDSSesBackToMark"	 * to allow for DRDAConnThread to "back-out" DSSes in the	 * event of errors.	 */	protected int markDSSClearPoint()	{		lastDSSBeforeMark = prevHdrLocation;		return offset;	}	/**	 * Does a logical "clear" of everything written to the buffer after	 * the received mark.  It's assumed that this method will be used	 * in error cases when we've started writing one or more DSSes,	 * but then hit an error and need to back out.  After backing out,	 * we'll always need to write _something_ back to the client to	 * indicate an error (typically, we just write an SQLCARD) but what	 * exactly gets written is handled in DRDAConnThread.  Here, we	 * just do the necessary prep so that whatever comes next will	 * succeed.	 */	protected void clearDSSesBackToMark(int mark)	{		// Logical clear.		offset = mark;		// Because we've just cleared out the most recently-		// written DSSes, we have to make sure the next thing		// we write will have the correct correlation id.  We		// do this by setting the value of 'nextCorrelationID'		// based on the chaining byte from the last remaining		// DSS (where "remaining" means that it still exists		// in the buffer after the clear).		if (lastDSSBeforeMark == -1)		// we cleared out the entire buffer; reset corr id.			nextCorrelationID = 1;		else {		// last remaining DSS had chaining, so we set "nextCorrelationID"		// to be 1 greater than whatever the last remaining DSS had as		// its correlation id. 			nextCorrelationID = 1 + (int)				(((bytes[lastDSSBeforeMark + 4] & 0xff) << 8) +				(bytes[lastDSSBeforeMark + 5] & 0xff));		}	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -