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)
{
Dictionary headers = 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)
{
Dictionary headers = 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
- SystemIcmpV6Statistics.cs
- VariableBinder.cs
- TokenBasedSetEnumerator.cs
- UrlPropertyAttribute.cs
- DBDataPermissionAttribute.cs
- documentation.cs
- SqlDataSourceQueryEditor.cs
- GeometryModel3D.cs
- TagNameToTypeMapper.cs
- ThreadTrace.cs
- UnsafeNativeMethods.cs
- AuthorizationContext.cs
- BasePropertyDescriptor.cs
- XAMLParseException.cs
- MaskInputRejectedEventArgs.cs
- WebRequestModuleElement.cs
- VirtualPathUtility.cs
- ExpressionNormalizer.cs
- XPathNode.cs
- TextRunProperties.cs
- CodeChecksumPragma.cs
- UnorderedHashRepartitionStream.cs
- SafeNativeMethods.cs
- DropSource.cs
- NumberFormatter.cs
- oledbmetadatacollectionnames.cs
- StylusCollection.cs
- OutputCacheSettingsSection.cs
- ParseElement.cs
- SqlClientMetaDataCollectionNames.cs
- InternalUserCancelledException.cs
- ProxyWebPartConnectionCollection.cs
- LayoutEditorPart.cs
- InternalRelationshipCollection.cs
- UnitySerializationHolder.cs
- TokenizerHelper.cs
- ScriptModule.cs
- ProviderConnectionPointCollection.cs
- EncoderNLS.cs
- UnsafeNativeMethods.cs
- MenuItemBindingCollection.cs
- FtpCachePolicyElement.cs
- InvalidAsynchronousStateException.cs
- SQLInt32.cs
- DisplayToken.cs
- SqlProviderManifest.cs
- CompareValidator.cs
- OutputWindow.cs
- SaveFileDialog.cs
- LocalBuilder.cs
- CollectionBuilder.cs
- AnnotationHelper.cs
- EventProperty.cs
- CheckedListBox.cs
- CodeAccessSecurityEngine.cs
- ServerValidateEventArgs.cs
- Completion.cs
- NominalTypeEliminator.cs
- SelectionRange.cs
- CallId.cs
- SelectedDatesCollection.cs
- MatrixUtil.cs
- XamlParser.cs
- TimeZoneNotFoundException.cs
- XmlSchemaComplexContentRestriction.cs
- IntegrationExceptionEventArgs.cs
- ClassHandlersStore.cs
- StrokeFIndices.cs
- Listbox.cs
- AttachedPropertyBrowsableAttribute.cs
- VideoDrawing.cs
- RenderDataDrawingContext.cs
- ConfigurationManagerInternalFactory.cs
- WSDualHttpSecurity.cs
- HashCodeCombiner.cs
- TransformGroup.cs
- WindowsRichEdit.cs
- DataViewListener.cs
- SettingsPropertyValue.cs
- ObjectFullSpanRewriter.cs
- Point.cs
- ResizingMessageFilter.cs
- ResourcesChangeInfo.cs
- InputLanguageSource.cs
- FieldToken.cs
- XmlSchemaExternal.cs
- OutputCacheSettings.cs
- ControlCollection.cs
- MultipleViewPatternIdentifiers.cs
- TimeSpan.cs
- VirtualizedItemProviderWrapper.cs
- MultiView.cs
- KeyPullup.cs
- Span.cs
- PartialCachingControl.cs
- EntityDescriptor.cs
- DefaultTypeArgumentAttribute.cs
- EntityClassGenerator.cs
- Help.cs
- CrossSiteScriptingValidation.cs