Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / ndp / fx / src / DataWeb / Client / System / Data / Services / Client / QueryAsyncResult.cs / 2 / 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 ////// Ends the asynchronous query request. /// ///Element type of the result. /// Source object of async request. /// The asyncResult being ended. ///Data service response. internal static QueryAsyncResult EndExecute(object source, IAsyncResult asyncResult) { QueryAsyncResult response = null; try { response = BaseAsyncResult.EndExecute (source, "Execute", asyncResult); } catch (InvalidOperationException ex) { response = asyncResult as QueryAsyncResult; Debug.Assert(response != null, "response != null, BaseAsyncResult.EndExecute() would have thrown a different exception otherwise."); QueryOperationResponse operationResponse = response.GetResponse(null, typeof(TElement)); if (operationResponse != null) { operationResponse.Error = ex; throw new DataServiceQueryException(Strings.DataServiceException_GeneralError, ex, operationResponse); } throw; } return response; } /// 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; if (null == response) { throw; } } 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); } } } } catch (Exception e) { this.HandleFailure(e); throw; } finally { this.SetCompleted(); 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; } } Debug.Assert(null != this.httpWebResponse || null != this.Failure, "should have response or exception"); if (null != this.httpWebResponse) { // 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.IsCompletedInternally && stream.CanRead); Debug.Assert(!reallyCompletedSynchronously || state.IsCompletedInternally, "AsyncEndGetResponse !IsCompleted"); } else { state.SetCompleted(); } } 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.IsCompletedInternally && stream.CanRead); Debug.Assert(!reallyCompletedSynchronously || state.IsCompletedInternally, "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.SetCompleted(); } } 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.IsCompletedInternally) { 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 ////// Ends the asynchronous query request. /// ///Element type of the result. /// Source object of async request. /// The asyncResult being ended. ///Data service response. internal static QueryAsyncResult EndExecute(object source, IAsyncResult asyncResult) { QueryAsyncResult response = null; try { response = BaseAsyncResult.EndExecute (source, "Execute", asyncResult); } catch (InvalidOperationException ex) { response = asyncResult as QueryAsyncResult; Debug.Assert(response != null, "response != null, BaseAsyncResult.EndExecute() would have thrown a different exception otherwise."); QueryOperationResponse operationResponse = response.GetResponse(null, typeof(TElement)); if (operationResponse != null) { operationResponse.Error = ex; throw new DataServiceQueryException(Strings.DataServiceException_GeneralError, ex, operationResponse); } throw; } return response; } /// 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; if (null == response) { throw; } } 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); } } } } catch (Exception e) { this.HandleFailure(e); throw; } finally { this.SetCompleted(); 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; } } Debug.Assert(null != this.httpWebResponse || null != this.Failure, "should have response or exception"); if (null != this.httpWebResponse) { // 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.IsCompletedInternally && stream.CanRead); Debug.Assert(!reallyCompletedSynchronously || state.IsCompletedInternally, "AsyncEndGetResponse !IsCompleted"); } else { state.SetCompleted(); } } 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.IsCompletedInternally && stream.CanRead); Debug.Assert(!reallyCompletedSynchronously || state.IsCompletedInternally, "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.SetCompleted(); } } 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.IsCompletedInternally) { 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
- LinqTreeNodeEvaluator.cs
- KernelTypeValidation.cs
- baseshape.cs
- TrustLevelCollection.cs
- SchemaExporter.cs
- StringStorage.cs
- OutOfProcStateClientManager.cs
- FileEnumerator.cs
- WsatConfiguration.cs
- COM2Enum.cs
- BuildProviderCollection.cs
- FutureFactory.cs
- GridItemProviderWrapper.cs
- DefinitionUpdate.cs
- httpserverutility.cs
- CorePropertiesFilter.cs
- IndicCharClassifier.cs
- LassoSelectionBehavior.cs
- TreeNode.cs
- PropertyMapper.cs
- MetricEntry.cs
- WebServiceHandlerFactory.cs
- CreateUserErrorEventArgs.cs
- AutomationProperty.cs
- FlowDocumentScrollViewerAutomationPeer.cs
- XmlAtomicValue.cs
- DispatcherEventArgs.cs
- MsmqOutputMessage.cs
- DiscreteKeyFrames.cs
- QuaternionKeyFrameCollection.cs
- InfoCardProofToken.cs
- FileUtil.cs
- FormDocumentDesigner.cs
- ValidationEventArgs.cs
- TrackingMemoryStream.cs
- DataGridViewLinkColumn.cs
- Clock.cs
- ProvidePropertyAttribute.cs
- DecoratedNameAttribute.cs
- ItemCheckEvent.cs
- BinaryExpressionHelper.cs
- XPathScanner.cs
- GridViewColumn.cs
- TextViewSelectionProcessor.cs
- OdbcEnvironment.cs
- StateRuntime.cs
- XmlText.cs
- NetCodeGroup.cs
- PropertyManager.cs
- RelatedImageListAttribute.cs
- TemplatedWizardStep.cs
- RegionInfo.cs
- SimplePropertyEntry.cs
- OracleCommand.cs
- HyperLink.cs
- PeerNearMe.cs
- XsltLoader.cs
- AttributeUsageAttribute.cs
- LogicalTreeHelper.cs
- Relationship.cs
- TemplateBaseAction.cs
- PartialCachingControl.cs
- HttpChannelHelper.cs
- FormatterServices.cs
- SafeSecurityHelper.cs
- HttpStreamMessageEncoderFactory.cs
- PagePropertiesChangingEventArgs.cs
- URI.cs
- XPathAncestorQuery.cs
- VisualTarget.cs
- MessageAction.cs
- BindingList.cs
- XmlSchemaChoice.cs
- ValidationEventArgs.cs
- DesignerGenericWebPart.cs
- SortDescription.cs
- HttpContext.cs
- SqlSelectClauseBuilder.cs
- HitTestParameters.cs
- FlowDocumentPage.cs
- ContextStack.cs
- DisplayNameAttribute.cs
- ContextInformation.cs
- Image.cs
- XamlTemplateSerializer.cs
- WmlControlAdapter.cs
- Drawing.cs
- DataSourceView.cs
- EdmComplexTypeAttribute.cs
- cache.cs
- activationcontext.cs
- InvalidOperationException.cs
- CodeGotoStatement.cs
- GregorianCalendar.cs
- SiteMapNodeItemEventArgs.cs
- Stacktrace.cs
- MediaScriptCommandRoutedEventArgs.cs
- XmlNullResolver.cs
- StsCommunicationException.cs
- SessionSwitchEventArgs.cs