Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Net / System / Net / Cache / _SingleItemRequestCache.cs / 1305376 / _SingleItemRequestCache.cs
/*++ Copyright (c) Microsoft Corporation Module Name: _SingleItemRequestCache.cs Abstract: Request Caching subsystem capable of caching one file at a time. Used by, for example, auto-proxy script downloading. Author: Justin Brown - Aug 2, 2004 Revision History: --*/ namespace System.Net.Cache { using System; using System.Net; using System.Diagnostics; using System.Text; using System.IO; using System.Collections.Specialized; using System.Threading; using System.Collections; internal class SingleItemRequestCache : #if !FEATURE_PAL Microsoft.Win32.WinInetCache #else RequestCache #endif { bool _UseWinInet; FrozenCacheEntry _Entry; private sealed class FrozenCacheEntry: RequestCacheEntry { byte[] _StreamBytes; string _Key; public FrozenCacheEntry(string key, RequestCacheEntry entry, Stream stream): this(key, entry, GetBytes(stream)) { } public FrozenCacheEntry(string key, RequestCacheEntry entry, byte[] streamBytes): base() { _Key = key; _StreamBytes = streamBytes; IsPrivateEntry = entry.IsPrivateEntry; StreamSize = entry.StreamSize; ExpiresUtc = entry.ExpiresUtc; HitCount = entry.HitCount; LastAccessedUtc = entry.LastAccessedUtc; entry.LastModifiedUtc = entry.LastModifiedUtc; LastSynchronizedUtc = entry.LastSynchronizedUtc; MaxStale = entry.MaxStale; UsageCount = entry.UsageCount; IsPartialEntry = entry.IsPartialEntry; EntryMetadata = entry.EntryMetadata; SystemMetadata = entry.SystemMetadata; } static byte[] GetBytes(Stream stream) { byte[] bytes; bool resize = false; if (stream.CanSeek) bytes = new byte[stream.Length]; else { resize = true; bytes = new byte[4096*2]; } int offset = 0; while (true) { int read = stream.Read(bytes, offset, bytes.Length-offset); if (read == 0) break; if ((offset+=read) == bytes.Length && resize) { byte[] newBytes = new byte[bytes.Length+4096*2]; Buffer.BlockCopy(bytes, 0, newBytes, 0, offset); bytes = newBytes; } } if (resize) { byte[] newBytes = new byte[offset]; Buffer.BlockCopy(bytes, 0, newBytes, 0, offset); bytes = newBytes; } return bytes; } public static FrozenCacheEntry Create(FrozenCacheEntry clonedObject) { return (object)clonedObject == (object)null? null: (FrozenCacheEntry) clonedObject.MemberwiseClone(); } public byte[] StreamBytes { get {return _StreamBytes;}} public string Key { get {return _Key;}} } internal SingleItemRequestCache(bool useWinInet) : #if !FEATURE_PAL base(true, true, false) #else base(true, true) #endif { _UseWinInet = useWinInet; } // Returns a read data stream and metadata associated with a cached entry. // Returns Stream.Null if there is no entry found. //An opened cache entry be preserved until the stream is closed. // internal override Stream Retrieve(string key, out RequestCacheEntry cacheEntry) { Stream result; if (!TryRetrieve(key, out cacheEntry, out result)) { FileNotFoundException fileNotFoundException = new FileNotFoundException(null, key); throw new IOException(SR.GetString(SR.net_cache_retrieve_failure, fileNotFoundException.Message), fileNotFoundException); } return result; } // Returns a write cache stream associated with the string Key. // Passed parameters allow cache to update an entry metadata accordingly. //The commit operation should happen on the stream closure. // internal override Stream Store(string key, long contentLength, DateTime expiresUtc, DateTime lastModifiedUtc, TimeSpan maxStale, StringCollection entryMetadata, StringCollection systemMetadata) { Stream result; if (!TryStore(key, contentLength, expiresUtc, lastModifiedUtc, maxStale, entryMetadata, systemMetadata, out result)) { FileNotFoundException fileNotFoundException = new FileNotFoundException(null, key); throw new IOException(SR.GetString(SR.net_cache_retrieve_failure, fileNotFoundException.Message), fileNotFoundException); } return result; } // // Removes an entry from the cache. // internal override void Remove(string key) { if (!TryRemove(key)) { FileNotFoundException fileNotFoundException = new FileNotFoundException(null, key); throw new IOException(SR.GetString(SR.net_cache_retrieve_failure, fileNotFoundException.Message), fileNotFoundException); } } // // Updates only metadata associated with a cached entry. // internal override void Update(string key, DateTime expiresUtc, DateTime lastModifiedUtc, DateTime lastSynchronizedUtc, TimeSpan maxStale, StringCollection entryMetadata, StringCollection systemMetadata) { if (!TryUpdate(key, expiresUtc, lastModifiedUtc, lastSynchronizedUtc, maxStale, entryMetadata, systemMetadata)) { FileNotFoundException fileNotFoundException = new FileNotFoundException(null, key); throw new IOException(SR.GetString(SR.net_cache_retrieve_failure, fileNotFoundException.Message), fileNotFoundException); } } internal override bool TryRetrieve(string key, out RequestCacheEntry cacheEntry, out Stream readStream) { if (key == null) throw new ArgumentNullException("key"); FrozenCacheEntry chkEntry = _Entry; cacheEntry = null; readStream = null; if (chkEntry == null || chkEntry.Key != key) { #if !FEATURE_PAL Stream realCacheStream; RequestCacheEntry realCacheEntry; if (!_UseWinInet || !base.TryRetrieve(key, out realCacheEntry, out realCacheStream)) return false; chkEntry = new FrozenCacheEntry(key, realCacheEntry, realCacheStream); // Relasing the WinInet entry earlier because we don't forward metadata-only updates ot it. realCacheStream.Close(); _Entry = chkEntry; #else return false; #endif } cacheEntry = FrozenCacheEntry.Create(chkEntry); readStream = new ReadOnlyStream(chkEntry.StreamBytes); return true; } internal override bool TryStore(string key, long contentLength, DateTime expiresUtc, DateTime lastModifiedUtc, TimeSpan maxStale, StringCollection entryMetadata, StringCollection systemMetadata, out Stream writeStream) { if (key == null) throw new ArgumentNullException("key"); RequestCacheEntry requestCacheEntry = new RequestCacheEntry(); requestCacheEntry.IsPrivateEntry = this.IsPrivateCache; requestCacheEntry.StreamSize = contentLength; requestCacheEntry.ExpiresUtc = expiresUtc; requestCacheEntry.LastModifiedUtc = lastModifiedUtc; requestCacheEntry.LastAccessedUtc = DateTime.UtcNow; requestCacheEntry.LastSynchronizedUtc = DateTime.UtcNow; requestCacheEntry.MaxStale = maxStale; requestCacheEntry.HitCount = 0; requestCacheEntry.UsageCount = 0; requestCacheEntry.IsPartialEntry = false; requestCacheEntry.EntryMetadata = entryMetadata; requestCacheEntry.SystemMetadata = systemMetadata; writeStream = null; Stream realWriteStream = null; #if !FEATURE_PAL if (_UseWinInet) { base.TryStore(key, contentLength, expiresUtc, lastModifiedUtc, maxStale, entryMetadata, systemMetadata, out realWriteStream); } #endif writeStream = new WriteOnlyStream(key, this, requestCacheEntry, realWriteStream); return true; } private void Commit(string key, RequestCacheEntry tempEntry, byte[] allBytes) { FrozenCacheEntry chkEntry = new FrozenCacheEntry(key, tempEntry, allBytes); _Entry = chkEntry; } internal override bool TryRemove(string key) { if (key == null) throw new ArgumentNullException("key"); #if !FEATURE_PAL if (_UseWinInet) { base.TryRemove(key); } #endif FrozenCacheEntry chkEntry = _Entry; if (chkEntry != null && chkEntry.Key == key) _Entry = null; return true; } internal override bool TryUpdate(string key, DateTime expiresUtc, DateTime lastModifiedUtc, DateTime lastSynchronizedUtc, TimeSpan maxStale, StringCollection entryMetadata, StringCollection systemMetadata) { if (key == null) throw new ArgumentNullException("key"); FrozenCacheEntry chkEntry = FrozenCacheEntry.Create(_Entry); // // This class does not forward metadata updates to WinInet to simplify the design and avoid interlocked ops // if (chkEntry == null || chkEntry.Key != key) return true; chkEntry.ExpiresUtc = expiresUtc; chkEntry.LastModifiedUtc = lastModifiedUtc; chkEntry.LastSynchronizedUtc = lastSynchronizedUtc; chkEntry.MaxStale = maxStale; chkEntry.EntryMetadata = entryMetadata; chkEntry.SystemMetadata = systemMetadata; _Entry = chkEntry; return true; } // // We've chosen to no forward to WinInet metadata-only updates // Hence our entries are never locked and this method does nothing // internal override void UnlockEntry(Stream stream) { } // // // internal class ReadOnlyStream : Stream, IRequestLifetimeTracker { private byte[] _Bytes; private int _Offset; private bool _Disposed; private int _ReadTimeout; private int _WriteTimeout; private RequestLifetimeSetter m_RequestLifetimeSetter; internal ReadOnlyStream(byte[] bytes): base() { _Bytes = bytes; _Offset = 0; _Disposed = false; _ReadTimeout = _WriteTimeout = -1; } public override bool CanRead {get {return true;}} public override bool CanSeek {get {return true;}} public override bool CanTimeout {get {return true;}} public override bool CanWrite {get {return false;}} public override long Length {get {return _Bytes.Length;}} public override long Position { get {return _Offset;} set { if (value < 0 || value > (long)_Bytes.Length) throw new ArgumentOutOfRangeException("value"); _Offset = (int)value; } } public override int ReadTimeout { get {return _ReadTimeout;} set { if (value<=0 && value!=System.Threading.Timeout.Infinite) throw new ArgumentOutOfRangeException("value", SR.GetString(SR.net_io_timeout_use_gt_zero)); _ReadTimeout = value; } } public override int WriteTimeout { get {return _WriteTimeout;} set { if (value<=0 && value!=System.Threading.Timeout.Infinite) throw new ArgumentOutOfRangeException("value", SR.GetString(SR.net_io_timeout_use_gt_zero)); _WriteTimeout = value; } } public override void Flush() {} public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, Object state) { int result = Read(buffer, offset, count); LazyAsyncResult ar = new LazyAsyncResult(null, state, callback); ar.InvokeCallback(result); return ar; } public override int EndRead(IAsyncResult asyncResult) { if (asyncResult == null) throw new ArgumentNullException("asyncResult"); LazyAsyncResult ar = (LazyAsyncResult) asyncResult; if (ar.EndCalled) throw new InvalidOperationException(SR.GetString(SR.net_io_invalidendcall, "EndRead")); ar.EndCalled = true; return (int)ar.InternalWaitForCompletion(); } public override int Read(byte[] buffer, int offset, int count) { if (_Disposed) throw new ObjectDisposedException(GetType().Name); if (buffer==null) throw new ArgumentNullException("buffer"); if (offset<0 || offset>buffer.Length) throw new ArgumentOutOfRangeException("offset"); if (count<0 || count>buffer.Length-offset) throw new ArgumentOutOfRangeException("count"); if (_Offset == _Bytes.Length) return 0; int chkOffset = (int)_Offset; count = Math.Min(count, _Bytes.Length - chkOffset); System.Buffer.BlockCopy(_Bytes, chkOffset, buffer, offset, count); chkOffset += count; _Offset = chkOffset; return count; } public override IAsyncResult BeginWrite(byte[] buffer, int offset, int size, AsyncCallback callback, Object state) { throw new NotSupportedException(SR.GetString(SR.net_readonlystream)); } public override void EndWrite(IAsyncResult asyncResult) { throw new NotSupportedException(SR.GetString(SR.net_readonlystream)); } public override void Write(byte[] buffer, int offset, int count) { throw new NotSupportedException(SR.GetString(SR.net_readonlystream)); } public override long Seek(long offset, SeekOrigin origin) { switch (origin) { case SeekOrigin.Begin: return Position = offset; case SeekOrigin.Current: return Position += offset; ///case SeekOrigin.End: return Position = _Bytes.Length-offset; default: throw new ArgumentException(SR.GetString(SR.net_invalid_enum, "SeekOrigin"), "origin"); } } public override void SetLength(long length) { throw new NotSupportedException(SR.GetString(SR.net_readonlystream)); } protected override void Dispose(bool disposing) { try { if (!_Disposed) { _Disposed = true; if (disposing) { RequestLifetimeSetter.Report(m_RequestLifetimeSetter); } } } finally { base.Dispose(disposing); } } internal byte[] Buffer { get { return _Bytes; } } void IRequestLifetimeTracker.TrackRequestLifetime(long requestStartTimestamp) { Debug.Assert(m_RequestLifetimeSetter == null, "TrackRequestLifetime called more than once."); m_RequestLifetimeSetter = new RequestLifetimeSetter(requestStartTimestamp); } } // // // private class WriteOnlyStream: Stream { private string _Key; private SingleItemRequestCache _Cache; private RequestCacheEntry _TempEntry; private Stream _RealStream; private long _TotalSize; private ArrayList _Buffers; private bool _Disposed; private int _ReadTimeout; private int _WriteTimeout; public WriteOnlyStream(string key, SingleItemRequestCache cache, RequestCacheEntry cacheEntry, Stream realWriteStream) { _Key = key; _Cache = cache; _TempEntry = cacheEntry; _RealStream = realWriteStream; _Buffers = new ArrayList(); } public override bool CanRead {get {return false;}} public override bool CanSeek {get {return false;}} public override bool CanTimeout {get {return true;}} public override bool CanWrite {get {return true;}} public override long Length {get {throw new NotSupportedException(SR.GetString(SR.net_writeonlystream));}} public override long Position { get {throw new NotSupportedException(SR.GetString(SR.net_writeonlystream));} set {throw new NotSupportedException(SR.GetString(SR.net_writeonlystream));} } public override int ReadTimeout { get {return _ReadTimeout;} set { if (value<=0 && value!=System.Threading.Timeout.Infinite) throw new ArgumentOutOfRangeException("value", SR.GetString(SR.net_io_timeout_use_gt_zero)); _ReadTimeout = value; } } public override int WriteTimeout { get {return _WriteTimeout;} set { if (value<=0 && value!=System.Threading.Timeout.Infinite) throw new ArgumentOutOfRangeException("value", SR.GetString(SR.net_io_timeout_use_gt_zero)); _WriteTimeout = value; } } public override void Flush() {} public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, Object state) {throw new NotSupportedException(SR.GetString(SR.net_writeonlystream));} public override int EndRead(IAsyncResult asyncResult) {throw new NotSupportedException(SR.GetString(SR.net_writeonlystream));} public override int Read(byte[] buffer, int offset, int count) {throw new NotSupportedException(SR.GetString(SR.net_writeonlystream));} public override long Seek(long offset, SeekOrigin origin) {throw new NotSupportedException(SR.GetString(SR.net_writeonlystream));} public override void SetLength(long length) {throw new NotSupportedException(SR.GetString(SR.net_writeonlystream));} public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, Object state) { Write(buffer, offset, count); LazyAsyncResult ar = new LazyAsyncResult(null, state, callback); ar.InvokeCallback(null); return ar; } public override void EndWrite(IAsyncResult asyncResult) { if (asyncResult == null) throw new ArgumentNullException("asyncResult"); LazyAsyncResult ar = (LazyAsyncResult) asyncResult; if (ar.EndCalled) throw new InvalidOperationException(SR.GetString(SR.net_io_invalidendcall, "EndWrite")); ar.EndCalled = true; ar.InternalWaitForCompletion(); } public override void Write(byte[] buffer, int offset, int count) { if (_Disposed) throw new ObjectDisposedException(GetType().Name); if (buffer==null) throw new ArgumentNullException("buffer"); if (offset<0 || offset>buffer.Length) throw new ArgumentOutOfRangeException("offset"); if (count<0 || count>buffer.Length-offset) throw new ArgumentOutOfRangeException("count"); if (_RealStream != null) try { _RealStream.Write(buffer, offset, count); } catch { _RealStream.Close(); _RealStream = null; } byte[] chunk = new byte[count]; System.Buffer.BlockCopy(buffer, offset, chunk, 0, count); _Buffers.Add(chunk); _TotalSize += count; } protected override void Dispose(bool disposing) { _Disposed = true; base.Dispose(disposing); // Do we mean to do this here???? if (disposing) { if (_RealStream != null) try { _RealStream.Close(); } catch { } byte[] allBytes = new byte[_TotalSize]; int offset = 0; for (int i = 0; i < _Buffers.Count; ++i) { byte[] buffer = (byte[])_Buffers[i]; Buffer.BlockCopy(buffer, 0, allBytes, offset, buffer.Length); offset += buffer.Length; } _Cache.Commit(_Key, _TempEntry, allBytes); } } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. /*++ Copyright (c) Microsoft Corporation Module Name: _SingleItemRequestCache.cs Abstract: Request Caching subsystem capable of caching one file at a time. Used by, for example, auto-proxy script downloading. Author: Justin Brown - Aug 2, 2004 Revision History: --*/ namespace System.Net.Cache { using System; using System.Net; using System.Diagnostics; using System.Text; using System.IO; using System.Collections.Specialized; using System.Threading; using System.Collections; internal class SingleItemRequestCache : #if !FEATURE_PAL Microsoft.Win32.WinInetCache #else RequestCache #endif { bool _UseWinInet; FrozenCacheEntry _Entry; private sealed class FrozenCacheEntry: RequestCacheEntry { byte[] _StreamBytes; string _Key; public FrozenCacheEntry(string key, RequestCacheEntry entry, Stream stream): this(key, entry, GetBytes(stream)) { } public FrozenCacheEntry(string key, RequestCacheEntry entry, byte[] streamBytes): base() { _Key = key; _StreamBytes = streamBytes; IsPrivateEntry = entry.IsPrivateEntry; StreamSize = entry.StreamSize; ExpiresUtc = entry.ExpiresUtc; HitCount = entry.HitCount; LastAccessedUtc = entry.LastAccessedUtc; entry.LastModifiedUtc = entry.LastModifiedUtc; LastSynchronizedUtc = entry.LastSynchronizedUtc; MaxStale = entry.MaxStale; UsageCount = entry.UsageCount; IsPartialEntry = entry.IsPartialEntry; EntryMetadata = entry.EntryMetadata; SystemMetadata = entry.SystemMetadata; } static byte[] GetBytes(Stream stream) { byte[] bytes; bool resize = false; if (stream.CanSeek) bytes = new byte[stream.Length]; else { resize = true; bytes = new byte[4096*2]; } int offset = 0; while (true) { int read = stream.Read(bytes, offset, bytes.Length-offset); if (read == 0) break; if ((offset+=read) == bytes.Length && resize) { byte[] newBytes = new byte[bytes.Length+4096*2]; Buffer.BlockCopy(bytes, 0, newBytes, 0, offset); bytes = newBytes; } } if (resize) { byte[] newBytes = new byte[offset]; Buffer.BlockCopy(bytes, 0, newBytes, 0, offset); bytes = newBytes; } return bytes; } public static FrozenCacheEntry Create(FrozenCacheEntry clonedObject) { return (object)clonedObject == (object)null? null: (FrozenCacheEntry) clonedObject.MemberwiseClone(); } public byte[] StreamBytes { get {return _StreamBytes;}} public string Key { get {return _Key;}} } internal SingleItemRequestCache(bool useWinInet) : #if !FEATURE_PAL base(true, true, false) #else base(true, true) #endif { _UseWinInet = useWinInet; } // Returns a read data stream and metadata associated with a cached entry. // Returns Stream.Null if there is no entry found. // An opened cache entry be preserved until the stream is closed. // internal override Stream Retrieve(string key, out RequestCacheEntry cacheEntry) { Stream result; if (!TryRetrieve(key, out cacheEntry, out result)) { FileNotFoundException fileNotFoundException = new FileNotFoundException(null, key); throw new IOException(SR.GetString(SR.net_cache_retrieve_failure, fileNotFoundException.Message), fileNotFoundException); } return result; } // Returns a write cache stream associated with the string Key. // Passed parameters allow cache to update an entry metadata accordingly. //The commit operation should happen on the stream closure. // internal override Stream Store(string key, long contentLength, DateTime expiresUtc, DateTime lastModifiedUtc, TimeSpan maxStale, StringCollection entryMetadata, StringCollection systemMetadata) { Stream result; if (!TryStore(key, contentLength, expiresUtc, lastModifiedUtc, maxStale, entryMetadata, systemMetadata, out result)) { FileNotFoundException fileNotFoundException = new FileNotFoundException(null, key); throw new IOException(SR.GetString(SR.net_cache_retrieve_failure, fileNotFoundException.Message), fileNotFoundException); } return result; } // // Removes an entry from the cache. // internal override void Remove(string key) { if (!TryRemove(key)) { FileNotFoundException fileNotFoundException = new FileNotFoundException(null, key); throw new IOException(SR.GetString(SR.net_cache_retrieve_failure, fileNotFoundException.Message), fileNotFoundException); } } // // Updates only metadata associated with a cached entry. // internal override void Update(string key, DateTime expiresUtc, DateTime lastModifiedUtc, DateTime lastSynchronizedUtc, TimeSpan maxStale, StringCollection entryMetadata, StringCollection systemMetadata) { if (!TryUpdate(key, expiresUtc, lastModifiedUtc, lastSynchronizedUtc, maxStale, entryMetadata, systemMetadata)) { FileNotFoundException fileNotFoundException = new FileNotFoundException(null, key); throw new IOException(SR.GetString(SR.net_cache_retrieve_failure, fileNotFoundException.Message), fileNotFoundException); } } internal override bool TryRetrieve(string key, out RequestCacheEntry cacheEntry, out Stream readStream) { if (key == null) throw new ArgumentNullException("key"); FrozenCacheEntry chkEntry = _Entry; cacheEntry = null; readStream = null; if (chkEntry == null || chkEntry.Key != key) { #if !FEATURE_PAL Stream realCacheStream; RequestCacheEntry realCacheEntry; if (!_UseWinInet || !base.TryRetrieve(key, out realCacheEntry, out realCacheStream)) return false; chkEntry = new FrozenCacheEntry(key, realCacheEntry, realCacheStream); // Relasing the WinInet entry earlier because we don't forward metadata-only updates ot it. realCacheStream.Close(); _Entry = chkEntry; #else return false; #endif } cacheEntry = FrozenCacheEntry.Create(chkEntry); readStream = new ReadOnlyStream(chkEntry.StreamBytes); return true; } internal override bool TryStore(string key, long contentLength, DateTime expiresUtc, DateTime lastModifiedUtc, TimeSpan maxStale, StringCollection entryMetadata, StringCollection systemMetadata, out Stream writeStream) { if (key == null) throw new ArgumentNullException("key"); RequestCacheEntry requestCacheEntry = new RequestCacheEntry(); requestCacheEntry.IsPrivateEntry = this.IsPrivateCache; requestCacheEntry.StreamSize = contentLength; requestCacheEntry.ExpiresUtc = expiresUtc; requestCacheEntry.LastModifiedUtc = lastModifiedUtc; requestCacheEntry.LastAccessedUtc = DateTime.UtcNow; requestCacheEntry.LastSynchronizedUtc = DateTime.UtcNow; requestCacheEntry.MaxStale = maxStale; requestCacheEntry.HitCount = 0; requestCacheEntry.UsageCount = 0; requestCacheEntry.IsPartialEntry = false; requestCacheEntry.EntryMetadata = entryMetadata; requestCacheEntry.SystemMetadata = systemMetadata; writeStream = null; Stream realWriteStream = null; #if !FEATURE_PAL if (_UseWinInet) { base.TryStore(key, contentLength, expiresUtc, lastModifiedUtc, maxStale, entryMetadata, systemMetadata, out realWriteStream); } #endif writeStream = new WriteOnlyStream(key, this, requestCacheEntry, realWriteStream); return true; } private void Commit(string key, RequestCacheEntry tempEntry, byte[] allBytes) { FrozenCacheEntry chkEntry = new FrozenCacheEntry(key, tempEntry, allBytes); _Entry = chkEntry; } internal override bool TryRemove(string key) { if (key == null) throw new ArgumentNullException("key"); #if !FEATURE_PAL if (_UseWinInet) { base.TryRemove(key); } #endif FrozenCacheEntry chkEntry = _Entry; if (chkEntry != null && chkEntry.Key == key) _Entry = null; return true; } internal override bool TryUpdate(string key, DateTime expiresUtc, DateTime lastModifiedUtc, DateTime lastSynchronizedUtc, TimeSpan maxStale, StringCollection entryMetadata, StringCollection systemMetadata) { if (key == null) throw new ArgumentNullException("key"); FrozenCacheEntry chkEntry = FrozenCacheEntry.Create(_Entry); // // This class does not forward metadata updates to WinInet to simplify the design and avoid interlocked ops // if (chkEntry == null || chkEntry.Key != key) return true; chkEntry.ExpiresUtc = expiresUtc; chkEntry.LastModifiedUtc = lastModifiedUtc; chkEntry.LastSynchronizedUtc = lastSynchronizedUtc; chkEntry.MaxStale = maxStale; chkEntry.EntryMetadata = entryMetadata; chkEntry.SystemMetadata = systemMetadata; _Entry = chkEntry; return true; } // // We've chosen to no forward to WinInet metadata-only updates // Hence our entries are never locked and this method does nothing // internal override void UnlockEntry(Stream stream) { } // // // internal class ReadOnlyStream : Stream, IRequestLifetimeTracker { private byte[] _Bytes; private int _Offset; private bool _Disposed; private int _ReadTimeout; private int _WriteTimeout; private RequestLifetimeSetter m_RequestLifetimeSetter; internal ReadOnlyStream(byte[] bytes): base() { _Bytes = bytes; _Offset = 0; _Disposed = false; _ReadTimeout = _WriteTimeout = -1; } public override bool CanRead {get {return true;}} public override bool CanSeek {get {return true;}} public override bool CanTimeout {get {return true;}} public override bool CanWrite {get {return false;}} public override long Length {get {return _Bytes.Length;}} public override long Position { get {return _Offset;} set { if (value < 0 || value > (long)_Bytes.Length) throw new ArgumentOutOfRangeException("value"); _Offset = (int)value; } } public override int ReadTimeout { get {return _ReadTimeout;} set { if (value<=0 && value!=System.Threading.Timeout.Infinite) throw new ArgumentOutOfRangeException("value", SR.GetString(SR.net_io_timeout_use_gt_zero)); _ReadTimeout = value; } } public override int WriteTimeout { get {return _WriteTimeout;} set { if (value<=0 && value!=System.Threading.Timeout.Infinite) throw new ArgumentOutOfRangeException("value", SR.GetString(SR.net_io_timeout_use_gt_zero)); _WriteTimeout = value; } } public override void Flush() {} public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, Object state) { int result = Read(buffer, offset, count); LazyAsyncResult ar = new LazyAsyncResult(null, state, callback); ar.InvokeCallback(result); return ar; } public override int EndRead(IAsyncResult asyncResult) { if (asyncResult == null) throw new ArgumentNullException("asyncResult"); LazyAsyncResult ar = (LazyAsyncResult) asyncResult; if (ar.EndCalled) throw new InvalidOperationException(SR.GetString(SR.net_io_invalidendcall, "EndRead")); ar.EndCalled = true; return (int)ar.InternalWaitForCompletion(); } public override int Read(byte[] buffer, int offset, int count) { if (_Disposed) throw new ObjectDisposedException(GetType().Name); if (buffer==null) throw new ArgumentNullException("buffer"); if (offset<0 || offset>buffer.Length) throw new ArgumentOutOfRangeException("offset"); if (count<0 || count>buffer.Length-offset) throw new ArgumentOutOfRangeException("count"); if (_Offset == _Bytes.Length) return 0; int chkOffset = (int)_Offset; count = Math.Min(count, _Bytes.Length - chkOffset); System.Buffer.BlockCopy(_Bytes, chkOffset, buffer, offset, count); chkOffset += count; _Offset = chkOffset; return count; } public override IAsyncResult BeginWrite(byte[] buffer, int offset, int size, AsyncCallback callback, Object state) { throw new NotSupportedException(SR.GetString(SR.net_readonlystream)); } public override void EndWrite(IAsyncResult asyncResult) { throw new NotSupportedException(SR.GetString(SR.net_readonlystream)); } public override void Write(byte[] buffer, int offset, int count) { throw new NotSupportedException(SR.GetString(SR.net_readonlystream)); } public override long Seek(long offset, SeekOrigin origin) { switch (origin) { case SeekOrigin.Begin: return Position = offset; case SeekOrigin.Current: return Position += offset; ///case SeekOrigin.End: return Position = _Bytes.Length-offset; default: throw new ArgumentException(SR.GetString(SR.net_invalid_enum, "SeekOrigin"), "origin"); } } public override void SetLength(long length) { throw new NotSupportedException(SR.GetString(SR.net_readonlystream)); } protected override void Dispose(bool disposing) { try { if (!_Disposed) { _Disposed = true; if (disposing) { RequestLifetimeSetter.Report(m_RequestLifetimeSetter); } } } finally { base.Dispose(disposing); } } internal byte[] Buffer { get { return _Bytes; } } void IRequestLifetimeTracker.TrackRequestLifetime(long requestStartTimestamp) { Debug.Assert(m_RequestLifetimeSetter == null, "TrackRequestLifetime called more than once."); m_RequestLifetimeSetter = new RequestLifetimeSetter(requestStartTimestamp); } } // // // private class WriteOnlyStream: Stream { private string _Key; private SingleItemRequestCache _Cache; private RequestCacheEntry _TempEntry; private Stream _RealStream; private long _TotalSize; private ArrayList _Buffers; private bool _Disposed; private int _ReadTimeout; private int _WriteTimeout; public WriteOnlyStream(string key, SingleItemRequestCache cache, RequestCacheEntry cacheEntry, Stream realWriteStream) { _Key = key; _Cache = cache; _TempEntry = cacheEntry; _RealStream = realWriteStream; _Buffers = new ArrayList(); } public override bool CanRead {get {return false;}} public override bool CanSeek {get {return false;}} public override bool CanTimeout {get {return true;}} public override bool CanWrite {get {return true;}} public override long Length {get {throw new NotSupportedException(SR.GetString(SR.net_writeonlystream));}} public override long Position { get {throw new NotSupportedException(SR.GetString(SR.net_writeonlystream));} set {throw new NotSupportedException(SR.GetString(SR.net_writeonlystream));} } public override int ReadTimeout { get {return _ReadTimeout;} set { if (value<=0 && value!=System.Threading.Timeout.Infinite) throw new ArgumentOutOfRangeException("value", SR.GetString(SR.net_io_timeout_use_gt_zero)); _ReadTimeout = value; } } public override int WriteTimeout { get {return _WriteTimeout;} set { if (value<=0 && value!=System.Threading.Timeout.Infinite) throw new ArgumentOutOfRangeException("value", SR.GetString(SR.net_io_timeout_use_gt_zero)); _WriteTimeout = value; } } public override void Flush() {} public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, Object state) {throw new NotSupportedException(SR.GetString(SR.net_writeonlystream));} public override int EndRead(IAsyncResult asyncResult) {throw new NotSupportedException(SR.GetString(SR.net_writeonlystream));} public override int Read(byte[] buffer, int offset, int count) {throw new NotSupportedException(SR.GetString(SR.net_writeonlystream));} public override long Seek(long offset, SeekOrigin origin) {throw new NotSupportedException(SR.GetString(SR.net_writeonlystream));} public override void SetLength(long length) {throw new NotSupportedException(SR.GetString(SR.net_writeonlystream));} public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, Object state) { Write(buffer, offset, count); LazyAsyncResult ar = new LazyAsyncResult(null, state, callback); ar.InvokeCallback(null); return ar; } public override void EndWrite(IAsyncResult asyncResult) { if (asyncResult == null) throw new ArgumentNullException("asyncResult"); LazyAsyncResult ar = (LazyAsyncResult) asyncResult; if (ar.EndCalled) throw new InvalidOperationException(SR.GetString(SR.net_io_invalidendcall, "EndWrite")); ar.EndCalled = true; ar.InternalWaitForCompletion(); } public override void Write(byte[] buffer, int offset, int count) { if (_Disposed) throw new ObjectDisposedException(GetType().Name); if (buffer==null) throw new ArgumentNullException("buffer"); if (offset<0 || offset>buffer.Length) throw new ArgumentOutOfRangeException("offset"); if (count<0 || count>buffer.Length-offset) throw new ArgumentOutOfRangeException("count"); if (_RealStream != null) try { _RealStream.Write(buffer, offset, count); } catch { _RealStream.Close(); _RealStream = null; } byte[] chunk = new byte[count]; System.Buffer.BlockCopy(buffer, offset, chunk, 0, count); _Buffers.Add(chunk); _TotalSize += count; } protected override void Dispose(bool disposing) { _Disposed = true; base.Dispose(disposing); // Do we mean to do this here???? if (disposing) { if (_RealStream != null) try { _RealStream.Close(); } catch { } byte[] allBytes = new byte[_TotalSize]; int offset = 0; for (int i = 0; i < _Buffers.Count; ++i) { byte[] buffer = (byte[])_Buffers[i]; Buffer.BlockCopy(buffer, 0, allBytes, offset, buffer.Length); offset += buffer.Length; } _Cache.Commit(_Key, _TempEntry, allBytes); } } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ChannelParameterCollection.cs
- SqlConnectionFactory.cs
- AtomEntry.cs
- DataSourceCollectionBase.cs
- ChildTable.cs
- DirectoryNotFoundException.cs
- LineBreak.cs
- DeploymentSectionCache.cs
- CodeSnippetTypeMember.cs
- FutureFactory.cs
- XmlDocumentType.cs
- SoapProtocolReflector.cs
- SHA1Cng.cs
- ToolStrip.cs
- MetadataException.cs
- OutKeywords.cs
- ScriptRegistrationManager.cs
- MenuAutomationPeer.cs
- RSAPKCS1KeyExchangeDeformatter.cs
- Int64.cs
- DataGridItemAttachedStorage.cs
- DPCustomTypeDescriptor.cs
- HideDisabledControlAdapter.cs
- TableSectionStyle.cs
- SettingsBase.cs
- ISO2022Encoding.cs
- DataGridViewComboBoxCell.cs
- Interfaces.cs
- StatusBarItemAutomationPeer.cs
- TypeUtil.cs
- MaskDesignerDialog.cs
- XmlHelper.cs
- DataSourceCache.cs
- AnimationClockResource.cs
- RuleAttributes.cs
- TextEditorDragDrop.cs
- WasAdminWrapper.cs
- InternalConfigEventArgs.cs
- DelegatingConfigHost.cs
- ProtocolViolationException.cs
- GeneratedCodeAttribute.cs
- EventDescriptor.cs
- BindingNavigatorDesigner.cs
- XhtmlTextWriter.cs
- ZipIOZip64EndOfCentralDirectoryLocatorBlock.cs
- SafeArrayRankMismatchException.cs
- CultureTableRecord.cs
- SyntaxCheck.cs
- TypeCollectionPropertyEditor.cs
- MessageFault.cs
- EntityParameter.cs
- PeerResolverSettings.cs
- ExpandableObjectConverter.cs
- OpenTypeLayout.cs
- UncommonField.cs
- URLMembershipCondition.cs
- TextDecoration.cs
- DataGridViewRowsAddedEventArgs.cs
- BitmapImage.cs
- FixedSOMSemanticBox.cs
- Win32SafeHandles.cs
- ExpressionBuilderCollection.cs
- MemoryPressure.cs
- Expander.cs
- cache.cs
- CompareInfo.cs
- OleCmdHelper.cs
- CapabilitiesAssignment.cs
- ReachPageContentCollectionSerializer.cs
- ToolStripComboBox.cs
- TextInfo.cs
- FileIOPermission.cs
- X500Name.cs
- TreeNodeEventArgs.cs
- QilFunction.cs
- ListDataHelper.cs
- FlowDocument.cs
- DataGridCommandEventArgs.cs
- Tokenizer.cs
- Solver.cs
- QueueProcessor.cs
- XomlCompilerParameters.cs
- WebEventCodes.cs
- PathFigureCollectionValueSerializer.cs
- ConfigXmlComment.cs
- MD5.cs
- AbsoluteQuery.cs
- DeadCharTextComposition.cs
- HtmlShimManager.cs
- ThicknessKeyFrameCollection.cs
- ResolveNextArgumentWorkItem.cs
- RootProjectionNode.cs
- GroupLabel.cs
- StringResourceManager.cs
- TextEditorSpelling.cs
- Calendar.cs
- _StreamFramer.cs
- ListBindingConverter.cs
- IndependentlyAnimatedPropertyMetadata.cs
- ConnectionStringsSection.cs