Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / ndp / fx / src / DataWeb / Client / System / Data / Services / Client / QueryAsyncResult.cs / 3 / QueryAsyncResult.cs
//---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // //// query object // //--------------------------------------------------------------------- namespace System.Data.Services.Client { using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; #if !ASTORIA_LIGHT // Data.Services http stack using System.Net; #else using System.Data.Services.Http; #endif ////// Wrapper HttpWebRequest & HttWebResponse /// internal class QueryAsyncResult : BaseAsyncResult { ///Originating service request internal readonly DataServiceRequest ServiceRequest; ///Originating WebRequest internal readonly HttpWebRequest Request; ///reusuable async copy buffer private static byte[] reusableAsyncCopyBuffer; ///content to write to request stream private MemoryStream requestStreamContent; ///active web request stream private Stream requestStream; ///web response, closed when completed private HttpWebResponse httpWebResponse; ///async response stream, closed when completed private Stream asyncResponseStream; ///buffer when copying async stream to response stream cache private byte[] asyncStreamCopyBuffer; ///response stream, returned to other parts of the system ///with async, the asyncResponseStream is copied into this stream private Stream responseStream; ///copy of HttpWebResponse.ContentType private string contentType; ///copy of HttpWebResponse.ContentLength private long contentLength; ///copy of HttpWebResponse.StatusCode private HttpStatusCode statusCode; ////// does this own the response stream or does the container of this QueryAsyncResult? /// private bool responseStreamOwner; ////// if the BeginRead has been called with asyncStreamCopyBuffer, but EndRead has not. /// do not return the buffer to general pool if any question of it being in use. /// private bool usingBuffer; #if StreamContainsBuffer ///does the responseStream contain the asyncStreamCopyBuffer? ///optimize reading in to the async buffer without copying into separate response stream private bool responseStreamIsCopyBuffer; #endif ///If CompletedSynchronously and asyncCompleteStep didn't increment, then underlying implementation lied. private int asyncCompleteStep; ///constructor /// source object of async request /// async method name on source object /// Originating serviceRequest /// Originating WebRequest /// user callback /// user state internal QueryAsyncResult(object source, string method, DataServiceRequest serviceRequest, HttpWebRequest request, AsyncCallback callback, object state) : base(source, method, callback, state) { Debug.Assert(null != request, "null request"); this.ServiceRequest = serviceRequest; this.Request = request; } #region HttpResponse wrapper - ContentLength, ContentType, StatusCode ///HttpWebResponse.ContentLength internal long ContentLength { get { return this.contentLength; } } ///HttpWebResponse.ContentType internal string ContentType { get { return this.contentType; } } ///HttpWebResponse.StatusCode internal HttpStatusCode StatusCode { get { return this.statusCode; } } #endregion ///wrapper for HttpWebResponse.GetResponseStream ///stream internal Stream GetResponseStream() { return this.responseStream; } ///start the asynchronous request /// content stream to send asynchronously in the request internal void BeginExecute(MemoryStream requestContent) { try { int step = ++this.asyncCompleteStep; IAsyncResult asyncResult; if ((null != requestContent) && (0 < requestContent.Length)) { requestContent.Position = 0; this.requestStreamContent = requestContent; this.Request.ContentLength = requestContent.Length; asyncResult = this.Request.BeginGetRequestStream(QueryAsyncResult.AsyncEndGetRequestStream, this); } else { asyncResult = this.Request.BeginGetResponse(QueryAsyncResult.AsyncEndGetResponse, this); } this.CompletedSynchronously &= asyncResult.CompletedSynchronously && (step < this.asyncCompleteStep); } catch (Exception e) { this.HandleFailure(e); throw; } finally { this.HandleCompleted(); } Debug.Assert(!this.CompletedSynchronously || this.IsCompleted, "if CompletedSynchronously then MUST IsCompleted"); } #if !ASTORIA_LIGHT ///Synchronous web request /// content stream to send in the request internal void Execute(MemoryStream requestContent) { try { if ((null != requestContent) && (0 < requestContent.Length)) { using (System.IO.Stream stream = Util.NullCheck(this.Request.GetRequestStream(), InternalError.InvalidGetRequestStream)) { byte[] buffer = requestContent.GetBuffer(); int bufferOffset = checked((int)requestContent.Position); int bufferLength = checked((int)requestContent.Length) - bufferOffset; // the following is useful in the debugging Immediate Window // string x = System.Text.Encoding.UTF8.GetString(buffer, bufferOffset, bufferLength); stream.Write(buffer, bufferOffset, bufferLength); } } HttpWebResponse response = null; try { response = (HttpWebResponse)this.Request.GetResponse(); } catch (WebException ex) { response = (HttpWebResponse)ex.Response; } this.SetHttpWebResponse(Util.NullCheck(response, InternalError.InvalidGetResponse)); if (HttpStatusCode.NoContent != this.StatusCode) { using (Stream stream = this.httpWebResponse.GetResponseStream()) { if (null != stream) { Stream copy = this.GetAsyncResponseStreamCopy(); this.responseStream = copy; Byte[] buffer = this.GetAsyncResponseStreamCopyBuffer(); long copied = WebUtil.CopyStream(stream, copy, ref buffer); if (this.responseStreamOwner) { if (0 == copied) { this.responseStream = null; } else if (copy.Position < copy.Length) { // In Silverlight, generally 3 bytes less than advertised by ContentLength are read ((MemoryStream)copy).SetLength(copy.Position); } } this.PutAsyncResponseStreamCopyBuffer(buffer); } } } } finally { this.IsCompleted = true; this.CompletedRequest(); } if (null != this.Failure) { throw this.Failure; } } #endif ////// Returns the response for the request. /// /// materialized results for the request. /// element type of the results. ///returns the instance of QueryOperationResponse containing the response. internal QueryOperationResponse GetResponse(IEnumerable results, Type elementType) { if (this.httpWebResponse != null) { Dictionaryheaders = WebUtil.WrapResponseHeaders(this.httpWebResponse); QueryOperationResponse response = QueryOperationResponse.GetInstance(elementType, headers, this.ServiceRequest, results); response.StatusCode = (int)this.httpWebResponse.StatusCode; return response; } return null; } /// cleanup work to do once the request has completed protected override void CompletedRequest() { Util.Dispose(ref this.asyncResponseStream); Util.Dispose(ref this.requestStream); Util.Dispose(ref this.requestStreamContent); byte[] buffer = this.asyncStreamCopyBuffer; this.asyncStreamCopyBuffer = null; #if StreamContainsBuffer if (!this.responseStreamIsCopyBuffer) #endif if ((null != buffer) && !this.usingBuffer) { this.PutAsyncResponseStreamCopyBuffer(buffer); } if (this.responseStreamOwner) { if (null != this.responseStream) { this.responseStream.Position = 0; } } // we've cached off what we need, headers still accessible after close this.httpWebResponse.Close(); Exception ex = DataServiceContext.HandleResponse(this.StatusCode, this.httpWebResponse.Headers[XmlConstants.HttpDataServiceVersion], this.GetResponseStream, false); if (null != ex) { this.HandleFailure(ex); } } ///get stream which of copy buffer (via response stream) will be copied into ///writtable stream, happens before GetAsyncResponseStreamCopyBuffer protected virtual Stream GetAsyncResponseStreamCopy() { this.responseStreamOwner = true; long length = this.contentLength; if ((0 < length) && (length <= Int32.MaxValue)) { Debug.Assert(null == this.asyncStreamCopyBuffer, "not expecting buffer"); byte[] buffer = new byte[(int)length]; #if StreamContainsBuffer if (length < UInt16.MaxValue) { // larger than this appears to cause trouble, specifically tested with 2619442 responseStreamIsCopyBuffer = true; this.asyncStreamCopyBuffer = buffer; } #endif return new MemoryStream(buffer, 0, buffer.Length, true, true); } return new MemoryStream(); } ///get buffer which response stream will be copied into ///writtable stream protected virtual byte[] GetAsyncResponseStreamCopyBuffer() { // consider having a cache of these buffers since they will be pinned Debug.Assert(null == this.asyncStreamCopyBuffer, "non-null this.asyncStreamCopyBuffer"); return System.Threading.Interlocked.Exchange(ref reusableAsyncCopyBuffer, null) ?? new byte[8000]; } ///returning a buffer after being done with it /// buffer to return protected virtual void PutAsyncResponseStreamCopyBuffer(byte[] buffer) { reusableAsyncCopyBuffer = buffer; } ///set the http web response /// response object protected virtual void SetHttpWebResponse(HttpWebResponse response) { this.httpWebResponse = response; this.statusCode = response.StatusCode; this.contentLength = response.ContentLength; this.contentType = response.ContentType; } ///handle request.BeginGetRequestStream with request.EndGetRquestStream and then write out request stream /// async result [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "required for this feature")] private static void AsyncEndGetRequestStream(IAsyncResult asyncResult) { QueryAsyncResult state = asyncResult.AsyncState as QueryAsyncResult; try { int step = CompleteCheck(state, InternalError.InvalidEndGetRequestCompleted); state.CompletedSynchronously &= asyncResult.CompletedSynchronously; // BeginGetRequestStream HttpWebRequest httpWebRequest = Util.NullCheck(state.Request, InternalError.InvalidEndGetRequestStreamRequest); Stream stream = Util.NullCheck(httpWebRequest.EndGetRequestStream(asyncResult), InternalError.InvalidEndGetRequestStreamStream); state.requestStream = stream; MemoryStream memoryStream = Util.NullCheck(state.requestStreamContent, InternalError.InvalidEndGetRequestStreamContent); byte[] buffer = memoryStream.GetBuffer(); int bufferOffset = checked((int)memoryStream.Position); int bufferLength = checked((int)memoryStream.Length) - bufferOffset; if ((null == buffer) || (0 == bufferLength)) { Error.ThrowInternalError(InternalError.InvalidEndGetRequestStreamContentLength); } // the following is useful in the debugging Immediate Window // string x = System.Text.Encoding.UTF8.GetString(buffer, bufferOffset, bufferLength); asyncResult = stream.BeginWrite(buffer, bufferOffset, bufferLength, QueryAsyncResult.AsyncEndWrite, state); bool reallyCompletedSynchronously = asyncResult.CompletedSynchronously && (step < state.asyncCompleteStep); state.CompletedSynchronously &= reallyCompletedSynchronously; // BeginWrite } catch (Exception e) { if (state.HandleFailure(e)) { throw; } } finally { state.HandleCompleted(); } } ///handle reqestStream.BeginWrite with requestStream.EndWrite then BeginGetResponse /// async result [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "required for this feature")] private static void AsyncEndWrite(IAsyncResult asyncResult) { QueryAsyncResult state = asyncResult.AsyncState as QueryAsyncResult; try { int step = CompleteCheck(state, InternalError.InvalidEndWriteCompleted); state.CompletedSynchronously &= asyncResult.CompletedSynchronously; // BeginWrite HttpWebRequest httpWebRequest = Util.NullCheck(state.Request, InternalError.InvalidEndWriteRequest); Stream stream = Util.NullCheck(state.requestStream, InternalError.InvalidEndWriteStream); stream.EndWrite(asyncResult); state.requestStream = null; stream.Dispose(); stream = state.requestStreamContent; if (null != stream) { state.requestStreamContent = null; stream.Dispose(); } asyncResult = httpWebRequest.BeginGetResponse(QueryAsyncResult.AsyncEndGetResponse, state); bool reallyCompletedSynchronously = asyncResult.CompletedSynchronously && (step < state.asyncCompleteStep); state.CompletedSynchronously &= reallyCompletedSynchronously; // BeginGetResponse } catch (Exception e) { if (state.HandleFailure(e)) { throw; } } finally { state.HandleCompleted(); } } ///handle request.BeginGetResponse with request.EndGetResponse and then copy response stream /// async result [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "required for this feature")] private static void AsyncEndGetResponse(IAsyncResult asyncResult) { QueryAsyncResult state = asyncResult.AsyncState as QueryAsyncResult; try { int step = CompleteCheck(state, InternalError.InvalidEndGetResponseCompleted); state.CompletedSynchronously &= asyncResult.CompletedSynchronously; // BeginGetResponse HttpWebRequest httpWebRequest = Util.NullCheck(state.Request, InternalError.InvalidEndGetResponseRequest); // the httpWebResponse is kept for batching, discarded by non-batch HttpWebResponse response = null; try { response = (HttpWebResponse)httpWebRequest.EndGetResponse(asyncResult); } catch (WebException e) { response = (HttpWebResponse)e.Response; if (null == response) { throw; } } state.SetHttpWebResponse(Util.NullCheck(response, InternalError.InvalidEndGetResponseResponse)); Debug.Assert(null == state.asyncResponseStream, "non-null asyncResponseStream"); Stream stream = null; if (HttpStatusCode.NoContent != response.StatusCode) { stream = response.GetResponseStream(); state.asyncResponseStream = stream; } if ((null != stream) && stream.CanRead) { if (null == state.responseStream) { // this is the stream we copy the reponse to state.responseStream = Util.NullCheck(state.GetAsyncResponseStreamCopy(), InternalError.InvalidAsyncResponseStreamCopy); } byte[] buffer = state.asyncStreamCopyBuffer; if (null == state.asyncStreamCopyBuffer) { // this is the buffer we read into and copy out of state.asyncStreamCopyBuffer = buffer = Util.NullCheck(state.GetAsyncResponseStreamCopyBuffer(), InternalError.InvalidAsyncResponseStreamCopyBuffer); } bool reallyCompletedSynchronously = false; do { int bufferOffset, bufferLength; #if StreamContainsBuffer if (state.responseStreamIsCopyBuffer) { // we may have asked for, but not received the entire stream bufferOffset = checked((int)state.responseStream.Position); bufferLength = buffer.Length - bufferOffset; } else #endif { bufferOffset = 0; bufferLength = buffer.Length; } state.usingBuffer = true; asyncResult = stream.BeginRead(buffer, bufferOffset, bufferLength, QueryAsyncResult.AsyncEndRead, state); reallyCompletedSynchronously = asyncResult.CompletedSynchronously && (step < state.asyncCompleteStep); state.CompletedSynchronously &= reallyCompletedSynchronously; // BeginRead } while (reallyCompletedSynchronously && !state.IsCompleted && stream.CanRead); Debug.Assert(!reallyCompletedSynchronously || state.IsCompleted, "AsyncEndGetResponse !IsCompleted"); } else { state.IsCompleted = true; } } catch (Exception e) { if (state.HandleFailure(e)) { throw; } } finally { state.HandleCompleted(); } } ///handle responseStream.BeginRead with responseStream.EndRead /// async result [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "required for this feature")] private static void AsyncEndRead(IAsyncResult asyncResult) { QueryAsyncResult state = asyncResult.AsyncState as QueryAsyncResult; int count = 0; try { int step = CompleteCheck(state, InternalError.InvalidEndReadCompleted); state.CompletedSynchronously &= asyncResult.CompletedSynchronously; // BeginRead Stream stream = Util.NullCheck(state.asyncResponseStream, InternalError.InvalidEndReadStream); Stream outputResponse = Util.NullCheck(state.responseStream, InternalError.InvalidEndReadCopy); byte[] buffer = Util.NullCheck(state.asyncStreamCopyBuffer, InternalError.InvalidEndReadBuffer); int bufferOffset = 0, bufferLength = 0; count = stream.EndRead(asyncResult); state.usingBuffer = false; if (0 < count) { #if StreamContainsBuffer if (state.responseStreamIsCopyBuffer) { // we may have asked for, but not received the entire stream outputResponse.Position = outputResponse.Position + count; bufferOffset = checked((int)outputResponse.Position); bufferLength = buffer.Length - bufferOffset; } else #endif { outputResponse.Write(buffer, 0, count); bufferOffset = 0; bufferLength = buffer.Length; } } if ((0 < bufferLength) && stream.CanRead) { if (!asyncResult.CompletedSynchronously) { // if CompletedSynchronously then caller will call and we reduce risk of stack overflow bool reallyCompletedSynchronously = false; do { state.usingBuffer = true; asyncResult = stream.BeginRead(buffer, bufferOffset, bufferLength, QueryAsyncResult.AsyncEndRead, state); reallyCompletedSynchronously = asyncResult.CompletedSynchronously && (step < state.asyncCompleteStep); state.CompletedSynchronously &= reallyCompletedSynchronously; // BeginRead } while (reallyCompletedSynchronously && !state.IsCompleted && stream.CanRead); Debug.Assert(!reallyCompletedSynchronously || state.IsCompleted, "AsyncEndRead !IsCompleted"); } } else { #if StreamContainsBuffer Debug.Assert(!state.responseStreamIsCopyBuffer || (outputResponse.Position == outputResponse.Length), "didn't read expected count"); #endif Debug.Assert(state.ContentLength < 0 || outputResponse.Length == state.ContentLength, "didn't read expected ContentLength"); if (outputResponse.Position < outputResponse.Length) { // In Silverlight, generally 3 bytes less than advertised by ContentLength are read ((MemoryStream)outputResponse).SetLength(outputResponse.Position); } state.IsCompleted = true; } } catch (Exception e) { if (state.HandleFailure(e)) { throw; } } finally { state.HandleCompleted(); } } ///verify non-null and not completed /// async result /// error code if null or completed ///the next step to validate CompletedSyncronously private static int CompleteCheck(QueryAsyncResult pereq, InternalError errorcode) { if ((null == pereq) || pereq.IsCompleted) { Error.ThrowInternalError(errorcode); } return ++pereq.asyncCompleteStep; } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // //// query object // //--------------------------------------------------------------------- namespace System.Data.Services.Client { using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; #if !ASTORIA_LIGHT // Data.Services http stack using System.Net; #else using System.Data.Services.Http; #endif ////// Wrapper HttpWebRequest & HttWebResponse /// internal class QueryAsyncResult : BaseAsyncResult { ///Originating service request internal readonly DataServiceRequest ServiceRequest; ///Originating WebRequest internal readonly HttpWebRequest Request; ///reusuable async copy buffer private static byte[] reusableAsyncCopyBuffer; ///content to write to request stream private MemoryStream requestStreamContent; ///active web request stream private Stream requestStream; ///web response, closed when completed private HttpWebResponse httpWebResponse; ///async response stream, closed when completed private Stream asyncResponseStream; ///buffer when copying async stream to response stream cache private byte[] asyncStreamCopyBuffer; ///response stream, returned to other parts of the system ///with async, the asyncResponseStream is copied into this stream private Stream responseStream; ///copy of HttpWebResponse.ContentType private string contentType; ///copy of HttpWebResponse.ContentLength private long contentLength; ///copy of HttpWebResponse.StatusCode private HttpStatusCode statusCode; ////// does this own the response stream or does the container of this QueryAsyncResult? /// private bool responseStreamOwner; ////// if the BeginRead has been called with asyncStreamCopyBuffer, but EndRead has not. /// do not return the buffer to general pool if any question of it being in use. /// private bool usingBuffer; #if StreamContainsBuffer ///does the responseStream contain the asyncStreamCopyBuffer? ///optimize reading in to the async buffer without copying into separate response stream private bool responseStreamIsCopyBuffer; #endif ///If CompletedSynchronously and asyncCompleteStep didn't increment, then underlying implementation lied. private int asyncCompleteStep; ///constructor /// source object of async request /// async method name on source object /// Originating serviceRequest /// Originating WebRequest /// user callback /// user state internal QueryAsyncResult(object source, string method, DataServiceRequest serviceRequest, HttpWebRequest request, AsyncCallback callback, object state) : base(source, method, callback, state) { Debug.Assert(null != request, "null request"); this.ServiceRequest = serviceRequest; this.Request = request; } #region HttpResponse wrapper - ContentLength, ContentType, StatusCode ///HttpWebResponse.ContentLength internal long ContentLength { get { return this.contentLength; } } ///HttpWebResponse.ContentType internal string ContentType { get { return this.contentType; } } ///HttpWebResponse.StatusCode internal HttpStatusCode StatusCode { get { return this.statusCode; } } #endregion ///wrapper for HttpWebResponse.GetResponseStream ///stream internal Stream GetResponseStream() { return this.responseStream; } ///start the asynchronous request /// content stream to send asynchronously in the request internal void BeginExecute(MemoryStream requestContent) { try { int step = ++this.asyncCompleteStep; IAsyncResult asyncResult; if ((null != requestContent) && (0 < requestContent.Length)) { requestContent.Position = 0; this.requestStreamContent = requestContent; this.Request.ContentLength = requestContent.Length; asyncResult = this.Request.BeginGetRequestStream(QueryAsyncResult.AsyncEndGetRequestStream, this); } else { asyncResult = this.Request.BeginGetResponse(QueryAsyncResult.AsyncEndGetResponse, this); } this.CompletedSynchronously &= asyncResult.CompletedSynchronously && (step < this.asyncCompleteStep); } catch (Exception e) { this.HandleFailure(e); throw; } finally { this.HandleCompleted(); } Debug.Assert(!this.CompletedSynchronously || this.IsCompleted, "if CompletedSynchronously then MUST IsCompleted"); } #if !ASTORIA_LIGHT ///Synchronous web request /// content stream to send in the request internal void Execute(MemoryStream requestContent) { try { if ((null != requestContent) && (0 < requestContent.Length)) { using (System.IO.Stream stream = Util.NullCheck(this.Request.GetRequestStream(), InternalError.InvalidGetRequestStream)) { byte[] buffer = requestContent.GetBuffer(); int bufferOffset = checked((int)requestContent.Position); int bufferLength = checked((int)requestContent.Length) - bufferOffset; // the following is useful in the debugging Immediate Window // string x = System.Text.Encoding.UTF8.GetString(buffer, bufferOffset, bufferLength); stream.Write(buffer, bufferOffset, bufferLength); } } HttpWebResponse response = null; try { response = (HttpWebResponse)this.Request.GetResponse(); } catch (WebException ex) { response = (HttpWebResponse)ex.Response; } this.SetHttpWebResponse(Util.NullCheck(response, InternalError.InvalidGetResponse)); if (HttpStatusCode.NoContent != this.StatusCode) { using (Stream stream = this.httpWebResponse.GetResponseStream()) { if (null != stream) { Stream copy = this.GetAsyncResponseStreamCopy(); this.responseStream = copy; Byte[] buffer = this.GetAsyncResponseStreamCopyBuffer(); long copied = WebUtil.CopyStream(stream, copy, ref buffer); if (this.responseStreamOwner) { if (0 == copied) { this.responseStream = null; } else if (copy.Position < copy.Length) { // In Silverlight, generally 3 bytes less than advertised by ContentLength are read ((MemoryStream)copy).SetLength(copy.Position); } } this.PutAsyncResponseStreamCopyBuffer(buffer); } } } } finally { this.IsCompleted = true; this.CompletedRequest(); } if (null != this.Failure) { throw this.Failure; } } #endif ////// Returns the response for the request. /// /// materialized results for the request. /// element type of the results. ///returns the instance of QueryOperationResponse containing the response. internal QueryOperationResponse GetResponse(IEnumerable results, Type elementType) { if (this.httpWebResponse != null) { Dictionaryheaders = WebUtil.WrapResponseHeaders(this.httpWebResponse); QueryOperationResponse response = QueryOperationResponse.GetInstance(elementType, headers, this.ServiceRequest, results); response.StatusCode = (int)this.httpWebResponse.StatusCode; return response; } return null; } /// cleanup work to do once the request has completed protected override void CompletedRequest() { Util.Dispose(ref this.asyncResponseStream); Util.Dispose(ref this.requestStream); Util.Dispose(ref this.requestStreamContent); byte[] buffer = this.asyncStreamCopyBuffer; this.asyncStreamCopyBuffer = null; #if StreamContainsBuffer if (!this.responseStreamIsCopyBuffer) #endif if ((null != buffer) && !this.usingBuffer) { this.PutAsyncResponseStreamCopyBuffer(buffer); } if (this.responseStreamOwner) { if (null != this.responseStream) { this.responseStream.Position = 0; } } // we've cached off what we need, headers still accessible after close this.httpWebResponse.Close(); Exception ex = DataServiceContext.HandleResponse(this.StatusCode, this.httpWebResponse.Headers[XmlConstants.HttpDataServiceVersion], this.GetResponseStream, false); if (null != ex) { this.HandleFailure(ex); } } ///get stream which of copy buffer (via response stream) will be copied into ///writtable stream, happens before GetAsyncResponseStreamCopyBuffer protected virtual Stream GetAsyncResponseStreamCopy() { this.responseStreamOwner = true; long length = this.contentLength; if ((0 < length) && (length <= Int32.MaxValue)) { Debug.Assert(null == this.asyncStreamCopyBuffer, "not expecting buffer"); byte[] buffer = new byte[(int)length]; #if StreamContainsBuffer if (length < UInt16.MaxValue) { // larger than this appears to cause trouble, specifically tested with 2619442 responseStreamIsCopyBuffer = true; this.asyncStreamCopyBuffer = buffer; } #endif return new MemoryStream(buffer, 0, buffer.Length, true, true); } return new MemoryStream(); } ///get buffer which response stream will be copied into ///writtable stream protected virtual byte[] GetAsyncResponseStreamCopyBuffer() { // consider having a cache of these buffers since they will be pinned Debug.Assert(null == this.asyncStreamCopyBuffer, "non-null this.asyncStreamCopyBuffer"); return System.Threading.Interlocked.Exchange(ref reusableAsyncCopyBuffer, null) ?? new byte[8000]; } ///returning a buffer after being done with it /// buffer to return protected virtual void PutAsyncResponseStreamCopyBuffer(byte[] buffer) { reusableAsyncCopyBuffer = buffer; } ///set the http web response /// response object protected virtual void SetHttpWebResponse(HttpWebResponse response) { this.httpWebResponse = response; this.statusCode = response.StatusCode; this.contentLength = response.ContentLength; this.contentType = response.ContentType; } ///handle request.BeginGetRequestStream with request.EndGetRquestStream and then write out request stream /// async result [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "required for this feature")] private static void AsyncEndGetRequestStream(IAsyncResult asyncResult) { QueryAsyncResult state = asyncResult.AsyncState as QueryAsyncResult; try { int step = CompleteCheck(state, InternalError.InvalidEndGetRequestCompleted); state.CompletedSynchronously &= asyncResult.CompletedSynchronously; // BeginGetRequestStream HttpWebRequest httpWebRequest = Util.NullCheck(state.Request, InternalError.InvalidEndGetRequestStreamRequest); Stream stream = Util.NullCheck(httpWebRequest.EndGetRequestStream(asyncResult), InternalError.InvalidEndGetRequestStreamStream); state.requestStream = stream; MemoryStream memoryStream = Util.NullCheck(state.requestStreamContent, InternalError.InvalidEndGetRequestStreamContent); byte[] buffer = memoryStream.GetBuffer(); int bufferOffset = checked((int)memoryStream.Position); int bufferLength = checked((int)memoryStream.Length) - bufferOffset; if ((null == buffer) || (0 == bufferLength)) { Error.ThrowInternalError(InternalError.InvalidEndGetRequestStreamContentLength); } // the following is useful in the debugging Immediate Window // string x = System.Text.Encoding.UTF8.GetString(buffer, bufferOffset, bufferLength); asyncResult = stream.BeginWrite(buffer, bufferOffset, bufferLength, QueryAsyncResult.AsyncEndWrite, state); bool reallyCompletedSynchronously = asyncResult.CompletedSynchronously && (step < state.asyncCompleteStep); state.CompletedSynchronously &= reallyCompletedSynchronously; // BeginWrite } catch (Exception e) { if (state.HandleFailure(e)) { throw; } } finally { state.HandleCompleted(); } } ///handle reqestStream.BeginWrite with requestStream.EndWrite then BeginGetResponse /// async result [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "required for this feature")] private static void AsyncEndWrite(IAsyncResult asyncResult) { QueryAsyncResult state = asyncResult.AsyncState as QueryAsyncResult; try { int step = CompleteCheck(state, InternalError.InvalidEndWriteCompleted); state.CompletedSynchronously &= asyncResult.CompletedSynchronously; // BeginWrite HttpWebRequest httpWebRequest = Util.NullCheck(state.Request, InternalError.InvalidEndWriteRequest); Stream stream = Util.NullCheck(state.requestStream, InternalError.InvalidEndWriteStream); stream.EndWrite(asyncResult); state.requestStream = null; stream.Dispose(); stream = state.requestStreamContent; if (null != stream) { state.requestStreamContent = null; stream.Dispose(); } asyncResult = httpWebRequest.BeginGetResponse(QueryAsyncResult.AsyncEndGetResponse, state); bool reallyCompletedSynchronously = asyncResult.CompletedSynchronously && (step < state.asyncCompleteStep); state.CompletedSynchronously &= reallyCompletedSynchronously; // BeginGetResponse } catch (Exception e) { if (state.HandleFailure(e)) { throw; } } finally { state.HandleCompleted(); } } ///handle request.BeginGetResponse with request.EndGetResponse and then copy response stream /// async result [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "required for this feature")] private static void AsyncEndGetResponse(IAsyncResult asyncResult) { QueryAsyncResult state = asyncResult.AsyncState as QueryAsyncResult; try { int step = CompleteCheck(state, InternalError.InvalidEndGetResponseCompleted); state.CompletedSynchronously &= asyncResult.CompletedSynchronously; // BeginGetResponse HttpWebRequest httpWebRequest = Util.NullCheck(state.Request, InternalError.InvalidEndGetResponseRequest); // the httpWebResponse is kept for batching, discarded by non-batch HttpWebResponse response = null; try { response = (HttpWebResponse)httpWebRequest.EndGetResponse(asyncResult); } catch (WebException e) { response = (HttpWebResponse)e.Response; if (null == response) { throw; } } state.SetHttpWebResponse(Util.NullCheck(response, InternalError.InvalidEndGetResponseResponse)); Debug.Assert(null == state.asyncResponseStream, "non-null asyncResponseStream"); Stream stream = null; if (HttpStatusCode.NoContent != response.StatusCode) { stream = response.GetResponseStream(); state.asyncResponseStream = stream; } if ((null != stream) && stream.CanRead) { if (null == state.responseStream) { // this is the stream we copy the reponse to state.responseStream = Util.NullCheck(state.GetAsyncResponseStreamCopy(), InternalError.InvalidAsyncResponseStreamCopy); } byte[] buffer = state.asyncStreamCopyBuffer; if (null == state.asyncStreamCopyBuffer) { // this is the buffer we read into and copy out of state.asyncStreamCopyBuffer = buffer = Util.NullCheck(state.GetAsyncResponseStreamCopyBuffer(), InternalError.InvalidAsyncResponseStreamCopyBuffer); } bool reallyCompletedSynchronously = false; do { int bufferOffset, bufferLength; #if StreamContainsBuffer if (state.responseStreamIsCopyBuffer) { // we may have asked for, but not received the entire stream bufferOffset = checked((int)state.responseStream.Position); bufferLength = buffer.Length - bufferOffset; } else #endif { bufferOffset = 0; bufferLength = buffer.Length; } state.usingBuffer = true; asyncResult = stream.BeginRead(buffer, bufferOffset, bufferLength, QueryAsyncResult.AsyncEndRead, state); reallyCompletedSynchronously = asyncResult.CompletedSynchronously && (step < state.asyncCompleteStep); state.CompletedSynchronously &= reallyCompletedSynchronously; // BeginRead } while (reallyCompletedSynchronously && !state.IsCompleted && stream.CanRead); Debug.Assert(!reallyCompletedSynchronously || state.IsCompleted, "AsyncEndGetResponse !IsCompleted"); } else { state.IsCompleted = true; } } catch (Exception e) { if (state.HandleFailure(e)) { throw; } } finally { state.HandleCompleted(); } } ///handle responseStream.BeginRead with responseStream.EndRead /// async result [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "required for this feature")] private static void AsyncEndRead(IAsyncResult asyncResult) { QueryAsyncResult state = asyncResult.AsyncState as QueryAsyncResult; int count = 0; try { int step = CompleteCheck(state, InternalError.InvalidEndReadCompleted); state.CompletedSynchronously &= asyncResult.CompletedSynchronously; // BeginRead Stream stream = Util.NullCheck(state.asyncResponseStream, InternalError.InvalidEndReadStream); Stream outputResponse = Util.NullCheck(state.responseStream, InternalError.InvalidEndReadCopy); byte[] buffer = Util.NullCheck(state.asyncStreamCopyBuffer, InternalError.InvalidEndReadBuffer); int bufferOffset = 0, bufferLength = 0; count = stream.EndRead(asyncResult); state.usingBuffer = false; if (0 < count) { #if StreamContainsBuffer if (state.responseStreamIsCopyBuffer) { // we may have asked for, but not received the entire stream outputResponse.Position = outputResponse.Position + count; bufferOffset = checked((int)outputResponse.Position); bufferLength = buffer.Length - bufferOffset; } else #endif { outputResponse.Write(buffer, 0, count); bufferOffset = 0; bufferLength = buffer.Length; } } if ((0 < bufferLength) && stream.CanRead) { if (!asyncResult.CompletedSynchronously) { // if CompletedSynchronously then caller will call and we reduce risk of stack overflow bool reallyCompletedSynchronously = false; do { state.usingBuffer = true; asyncResult = stream.BeginRead(buffer, bufferOffset, bufferLength, QueryAsyncResult.AsyncEndRead, state); reallyCompletedSynchronously = asyncResult.CompletedSynchronously && (step < state.asyncCompleteStep); state.CompletedSynchronously &= reallyCompletedSynchronously; // BeginRead } while (reallyCompletedSynchronously && !state.IsCompleted && stream.CanRead); Debug.Assert(!reallyCompletedSynchronously || state.IsCompleted, "AsyncEndRead !IsCompleted"); } } else { #if StreamContainsBuffer Debug.Assert(!state.responseStreamIsCopyBuffer || (outputResponse.Position == outputResponse.Length), "didn't read expected count"); #endif Debug.Assert(state.ContentLength < 0 || outputResponse.Length == state.ContentLength, "didn't read expected ContentLength"); if (outputResponse.Position < outputResponse.Length) { // In Silverlight, generally 3 bytes less than advertised by ContentLength are read ((MemoryStream)outputResponse).SetLength(outputResponse.Position); } state.IsCompleted = true; } } catch (Exception e) { if (state.HandleFailure(e)) { throw; } } finally { state.HandleCompleted(); } } ///verify non-null and not completed /// async result /// error code if null or completed ///the next step to validate CompletedSyncronously private static int CompleteCheck(QueryAsyncResult pereq, InternalError errorcode) { if ((null == pereq) || pereq.IsCompleted) { Error.ThrowInternalError(errorcode); } return ++pereq.asyncCompleteStep; } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ExpressionBuilder.cs
- FormViewCommandEventArgs.cs
- SoapTypeAttribute.cs
- TraceContextEventArgs.cs
- ObjectFullSpanRewriter.cs
- _AcceptOverlappedAsyncResult.cs
- QueryOperationResponseOfT.cs
- QueueProcessor.cs
- Win32Exception.cs
- MobileUserControlDesigner.cs
- UrlMappingsSection.cs
- RepeaterItemEventArgs.cs
- CalculatedColumn.cs
- WebPart.cs
- WebHttpBindingElement.cs
- MetafileEditor.cs
- SynchronizationScope.cs
- PersonalizationState.cs
- SafeNativeMethods.cs
- CustomWebEventKey.cs
- WizardDesigner.cs
- BamlBinaryWriter.cs
- GenericEnumConverter.cs
- ActiveXSite.cs
- DataRecordObjectView.cs
- DeflateEmulationStream.cs
- ExternalCalls.cs
- Annotation.cs
- TrackingParticipant.cs
- Schema.cs
- Metadata.cs
- HttpDebugHandler.cs
- TypeGeneratedEventArgs.cs
- DataGridLengthConverter.cs
- OdbcConnection.cs
- streamingZipPartStream.cs
- CommandID.cs
- ColorAnimationBase.cs
- ChangeTracker.cs
- XmlSchemaSimpleTypeRestriction.cs
- OracleBFile.cs
- HtmlInputText.cs
- RoutedEventValueSerializer.cs
- TargetException.cs
- LocalBuilder.cs
- EventLogPermissionAttribute.cs
- WebRequest.cs
- XmlSerializerAssemblyAttribute.cs
- ColorContextHelper.cs
- ListControlBuilder.cs
- WebPartConnectionCollection.cs
- ForEach.cs
- ToolStripMenuItem.cs
- BuiltInExpr.cs
- MappedMetaModel.cs
- DebuggerAttributes.cs
- LogicalTreeHelper.cs
- UInt32.cs
- ObjectListFieldCollection.cs
- ModelVisual3D.cs
- ProfileParameter.cs
- NativeMethodsOther.cs
- Int32CollectionValueSerializer.cs
- ChannelHandler.cs
- HostedBindingBehavior.cs
- MeasurementDCInfo.cs
- ToggleProviderWrapper.cs
- XPathDocumentBuilder.cs
- TransactionManager.cs
- HttpHeaderCollection.cs
- LabelExpression.cs
- CustomErrorCollection.cs
- StyleHelper.cs
- OutputScopeManager.cs
- WebConfigurationHost.cs
- FormView.cs
- ParseHttpDate.cs
- ListViewTableCell.cs
- FilteredDataSetHelper.cs
- FloaterBaseParagraph.cs
- EmptyCollection.cs
- ServiceEndpointCollection.cs
- DragDeltaEventArgs.cs
- FlowDocumentScrollViewer.cs
- WindowsToolbarItemAsMenuItem.cs
- Separator.cs
- TabItem.cs
- HttpModulesSection.cs
- GZipDecoder.cs
- XmlSiteMapProvider.cs
- DBConcurrencyException.cs
- PropertyRef.cs
- _LoggingObject.cs
- ContentPlaceHolder.cs
- _Semaphore.cs
- RepeaterCommandEventArgs.cs
- TemplateControlCodeDomTreeGenerator.cs
- BooleanAnimationBase.cs
- XmlnsDefinitionAttribute.cs
- Tool.cs