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
- WebPartVerb.cs
- OdbcConnectionPoolProviderInfo.cs
- CTreeGenerator.cs
- RegexBoyerMoore.cs
- ComponentDispatcher.cs
- FixedDocumentSequencePaginator.cs
- MatrixTransform3D.cs
- XmlSchemaImport.cs
- LineServices.cs
- elementinformation.cs
- LinkLabel.cs
- TransportManager.cs
- EmbeddedMailObjectsCollection.cs
- DbTransaction.cs
- ActivityTypeDesigner.xaml.cs
- ContentAlignmentEditor.cs
- Gdiplus.cs
- SecurityNegotiationException.cs
- RtfFormatStack.cs
- OleDbInfoMessageEvent.cs
- HashSetEqualityComparer.cs
- QuaternionIndependentAnimationStorage.cs
- DataSourceUtil.cs
- PointLightBase.cs
- UrlAuthFailedErrorFormatter.cs
- AttributeEmitter.cs
- SafeProcessHandle.cs
- MsmqInputMessage.cs
- InputLanguageProfileNotifySink.cs
- GridViewDeleteEventArgs.cs
- SqlXml.cs
- FrameAutomationPeer.cs
- RadioButtonDesigner.cs
- SizeConverter.cs
- ProcessManager.cs
- ShimAsPublicXamlType.cs
- InstanceOwnerQueryResult.cs
- XmlDataSourceView.cs
- QueryTask.cs
- OleDragDropHandler.cs
- HtmlElementEventArgs.cs
- ExcCanonicalXml.cs
- ColorAnimation.cs
- DocumentGridPage.cs
- EncoderExceptionFallback.cs
- OledbConnectionStringbuilder.cs
- MemberMemberBinding.cs
- OuterGlowBitmapEffect.cs
- Image.cs
- PenContexts.cs
- StringKeyFrameCollection.cs
- ObjectIDGenerator.cs
- BitmapEffectDrawingContent.cs
- StructureChangedEventArgs.cs
- ShapeTypeface.cs
- EntityUtil.cs
- SqlCommandBuilder.cs
- ToolboxCategoryItems.cs
- XXXOnTypeBuilderInstantiation.cs
- FixedSOMImage.cs
- DataObjectCopyingEventArgs.cs
- OpenTypeLayoutCache.cs
- GeneralTransformGroup.cs
- MarkupProperty.cs
- ScopelessEnumAttribute.cs
- SqlNodeAnnotation.cs
- CodeExpressionRuleDeclaration.cs
- Attribute.cs
- WebPartTransformer.cs
- ZoneButton.cs
- FixedPage.cs
- SoapEnvelopeProcessingElement.cs
- Tokenizer.cs
- SqlServer2KCompatibilityCheck.cs
- QilExpression.cs
- TextEditorSelection.cs
- Ops.cs
- TdsParserSessionPool.cs
- FontWeightConverter.cs
- ColorDialog.cs
- GenericWebPart.cs
- List.cs
- SynchronizationLockException.cs
- BackgroundFormatInfo.cs
- BindingExpressionBase.cs
- UnrecognizedPolicyAssertionElement.cs
- ApplicationServiceManager.cs
- DependencyObject.cs
- NativeMethods.cs
- EventPropertyMap.cs
- DomNameTable.cs
- FormViewPagerRow.cs
- UpdatePanelTrigger.cs
- MeasurementDCInfo.cs
- AuthenticatingEventArgs.cs
- MetadataProperty.cs
- FilterException.cs
- ComponentConverter.cs
- PeerEndPoint.cs
- ImageAttributes.cs