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 cacheEntry = new RequestCacheEntry { IsPrivateEntry = base.IsPrivateCache, StreamSize = contentLength, ExpiresUtc = expiresUtc, LastModifiedUtc = lastModifiedUtc, LastAccessedUtc = DateTime.UtcNow, LastSynchronizedUtc = DateTime.UtcNow, MaxStale = maxStale, HitCount = 0, UsageCount = 0, IsPartialEntry = false, EntryMetadata = entryMetadata, SystemMetadata = systemMetadata }; writeStream = null; Stream stream = null; if (this._UseWinInet) { base.TryStore(key, contentLength, expiresUtc, lastModifiedUtc, maxStale, entryMetadata, systemMetadata, out stream); } writeStream = new WriteOnlyStream(key, this, cacheEntry, stream); return(true); }
internal override bool TryRetrieve(string key, out RequestCacheEntry cacheEntry, out Stream readStream) { if (key == null) { throw new ArgumentNullException("key"); } FrozenCacheEntry clonedObject = this._Entry; cacheEntry = null; readStream = null; if ((clonedObject == null) || (clonedObject.Key != key)) { Stream stream; RequestCacheEntry entry2; if (!this._UseWinInet || !base.TryRetrieve(key, out entry2, out stream)) { return(false); } clonedObject = new FrozenCacheEntry(key, entry2, stream); stream.Close(); this._Entry = clonedObject; } cacheEntry = FrozenCacheEntry.Create(clonedObject); readStream = new ReadOnlyStream(clonedObject.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; writeStream = new WriteOnlyStream(key, this, requestCacheEntry, realWriteStream); return(true); }
internal override bool TryRetrieve(string key, out RequestCacheEntry cacheEntry, out Stream readStream) { if (key == null) { throw new ArgumentNullException("key"); } FrozenCacheEntry clonedObject = this._Entry; cacheEntry = null; readStream = null; if ((clonedObject == null) || (clonedObject.Key != key)) { Stream stream; RequestCacheEntry entry2; if (!this._UseWinInet || !base.TryRetrieve(key, out entry2, out stream)) { return false; } clonedObject = new FrozenCacheEntry(key, entry2, stream); stream.Close(); this._Entry = clonedObject; } cacheEntry = FrozenCacheEntry.Create(clonedObject); readStream = new ReadOnlyStream(clonedObject.StreamBytes); return true; }
public WriteOnlyStream(string key, SingleItemRequestCache cache, RequestCacheEntry cacheEntry, Stream realWriteStream) { this._Key = key; this._Cache = cache; this._TempEntry = cacheEntry; this._RealStream = realWriteStream; this._Buffers = new ArrayList(); }
// internal override bool TryRetrieve(string key, out RequestCacheEntry cacheEntry, out Stream readStream) { readStream = Lookup(key, out cacheEntry, false); if (readStream == null) { return false; } return true; }
internal override Stream Retrieve(string key, out RequestCacheEntry cacheEntry) { Stream stream; if (!this.TryRetrieve(key, out cacheEntry, out stream)) { FileNotFoundException innerException = new FileNotFoundException(null, key); throw new IOException(SR.GetString("net_cache_retrieve_failure", new object[] { innerException.Message }), innerException); } return stream; }
internal override Stream Retrieve(string key, out RequestCacheEntry cacheEntry) { Stream stream; if (!this.TryRetrieve(key, out cacheEntry, out stream)) { FileNotFoundException innerException = new FileNotFoundException(null, key); throw new IOException(SR.GetString("net_cache_retrieve_failure", new object[] { innerException.Message }), innerException); } return(stream); }
// Returns a read data stream and metadata associated with a cached entry. // Returns Stream.Null if there is no entry found. // <remarks> An opened cache entry be preserved until the stream is closed. </remarks> // 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); }
// // // private void ValidateFreshness(RequestCacheEntry fetchEntry) { _Validator.FetchCacheEntry(fetchEntry); if (_Validator.CacheStream == null || _Validator.CacheStream == Stream.Null) { if (Logging.On) { Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_entry_not_found_freshness_undefined, "ValidateFreshness()")); } _Validator.SetFreshnessStatus(CacheFreshnessStatus.Undefined); return; } if (Logging.On) { if (Logging.IsVerbose(Logging.RequestCache)) { Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_dumping_cache_context)); if (fetchEntry == null) { Logging.PrintInfo(Logging.RequestCache, "<null>"); } else { string[] context = fetchEntry.ToString(Logging.IsVerbose(Logging.RequestCache)).Split(RequestCache.LineSplits); for (int i = 0; i < context.Length; ++i) { if (context[i].Length != 0) { Logging.PrintInfo(Logging.RequestCache, context[i]); } } } } } CacheFreshnessStatus result = _Validator.ValidateFreshness(); _Validator.SetFreshnessStatus(result); _IsCacheFresh = result == CacheFreshnessStatus.Fresh; if (Logging.On) { Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_result, "ValidateFreshness()", result.ToString())); } }
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; }
public FrozenCacheEntry(string key, RequestCacheEntry entry, byte[] streamBytes) { this._Key = key; this._StreamBytes = streamBytes; base.IsPrivateEntry = entry.IsPrivateEntry; base.StreamSize = entry.StreamSize; base.ExpiresUtc = entry.ExpiresUtc; base.HitCount = entry.HitCount; base.LastAccessedUtc = entry.LastAccessedUtc; entry.LastModifiedUtc = entry.LastModifiedUtc; base.LastSynchronizedUtc = entry.LastSynchronizedUtc; base.MaxStale = entry.MaxStale; base.UsageCount = entry.UsageCount; base.IsPartialEntry = entry.IsPartialEntry; base.EntryMetadata = entry.EntryMetadata; base.SystemMetadata = entry.SystemMetadata; }
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; }
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) { return(false); } cacheEntry = FrozenCacheEntry.Create(chkEntry); readStream = new ReadOnlyStream(chkEntry.StreamBytes); return(true); }
private void ValidateFreshness(RequestCacheEntry fetchEntry) { this._Validator.FetchCacheEntry(fetchEntry); if ((this._Validator.CacheStream == null) || (this._Validator.CacheStream == Stream.Null)) { if (Logging.On) { Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_entry_not_found_freshness_undefined", new object[] { "ValidateFreshness()" })); } this._Validator.SetFreshnessStatus(CacheFreshnessStatus.Undefined); } else { if (Logging.On && Logging.IsVerbose(Logging.RequestCache)) { Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_dumping_cache_context")); if (fetchEntry == null) { Logging.PrintInfo(Logging.RequestCache, "<null>"); } else { string[] strArray = fetchEntry.ToString(Logging.IsVerbose(Logging.RequestCache)).Split(RequestCache.LineSplits); for (int i = 0; i < strArray.Length; i++) { if (strArray[i].Length != 0) { Logging.PrintInfo(Logging.RequestCache, strArray[i]); } } } } CacheFreshnessStatus status = this._Validator.ValidateFreshness(); this._Validator.SetFreshnessStatus(status); this._IsCacheFresh = status == CacheFreshnessStatus.Fresh; if (Logging.On) { Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_result", new object[] { "ValidateFreshness()", status.ToString() })); } } }
private unsafe Stream Lookup(string key, out RequestCacheEntry cacheEntry, bool isThrow) { if (Logging.On) { Logging.Enter(Logging.RequestCache, "WinInetCache.Retrieve", "key = " + key); } if (key == null) { throw new ArgumentNullException("key"); } Stream @null = Stream.Null; SafeUnlockUrlCacheEntryFile handle = null; _WinInetCache.Entry entry = new _WinInetCache.Entry(key, _MaximumResponseHeadersLength); try { handle = _WinInetCache.LookupFile(entry); if (entry.Error == _WinInetCache.Status.Success) { if (Logging.On) { Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_filename", new object[] { "WinInetCache.Retrieve()", entry.Filename, entry.Error })); } cacheEntry = new RequestCacheEntry(entry, base.IsPrivateCache); if ((entry.MetaInfo != null) && (entry.MetaInfo.Length != 0)) { int startIndex = 0; int length = entry.MetaInfo.Length; StringCollection strings = new StringCollection(); fixed (char* str2 = ((char*) entry.MetaInfo)) { char* chPtr = str2; for (int i = 0; i < length; i++) { if ((((i == startIndex) && ((i + 2) < length)) && (chPtr[i] == '~')) && (((chPtr[i + 1] == 'U') || (chPtr[i + 1] == 'u')) && (chPtr[i + 2] == ':'))) { while ((i < length) && (chPtr[++i] != '\n')) { } startIndex = i + 1; } else if (((i + 1) == length) || (chPtr[i] == '\n')) { string str = entry.MetaInfo.Substring(startIndex, ((chPtr[i - 1] == '\r') ? (i - 1) : (i + 1)) - startIndex); if ((str.Length == 0) && (cacheEntry.EntryMetadata == null)) { cacheEntry.EntryMetadata = strings; strings = new StringCollection(); } else if ((cacheEntry.EntryMetadata != null) && str.StartsWith("~SPARSE_ENTRY:", StringComparison.Ordinal)) { cacheEntry.IsPartialEntry = true; } else { strings.Add(str); } startIndex = i + 1; } } } if (cacheEntry.EntryMetadata == null) { cacheEntry.EntryMetadata = strings; } else { cacheEntry.SystemMetadata = strings; } } @null = new ReadStream(entry, handle, this.async); } else { if (handle != null) { handle.Close(); } cacheEntry = new RequestCacheEntry(); cacheEntry.IsPrivateEntry = base.IsPrivateCache; if (entry.Error != _WinInetCache.Status.FileNotFound) { if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString("net_log_cache_lookup_failed", new object[] { "WinInetCache.Retrieve()", new Win32Exception((int) entry.Error).Message })); } if (Logging.On) { Logging.Exit(Logging.RequestCache, "WinInetCache.Retrieve()"); } if (isThrow) { Win32Exception innerException = new Win32Exception((int) entry.Error); throw new IOException(SR.GetString("net_cache_retrieve_failure", new object[] { innerException.Message }), innerException); } return null; } } } catch (Exception exception2) { if (((exception2 is ThreadAbortException) || (exception2 is StackOverflowException)) || (exception2 is OutOfMemoryException)) { throw; } if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString("net_log_cache_exception", new object[] { "WinInetCache.Retrieve()", exception2.ToString() })); } if (Logging.On) { Logging.Exit(Logging.RequestCache, "WinInetCache.Retrieve()"); } if (handle != null) { handle.Close(); } @null.Close(); @null = Stream.Null; cacheEntry = new RequestCacheEntry(); cacheEntry.IsPrivateEntry = base.IsPrivateCache; if (isThrow) { throw; } return null; } if (Logging.On) { Logging.Exit(Logging.RequestCache, "WinInetCache.Retrieve()", "Status = " + entry.Error.ToString()); } return @null; }
internal override Stream Retrieve(string key, out RequestCacheEntry cacheEntry) { return this.Lookup(key, out cacheEntry, true); }
public FrozenCacheEntry(string key, RequestCacheEntry entry, Stream stream) : this(key, entry, GetBytes(stream)) { }
private void CheckRetrieveBeforeSubmit() { try { RequestCacheEntry entry; Label_0000: if ((this._Validator.CacheStream != null) && (this._Validator.CacheStream != Stream.Null)) { this._Validator.CacheStream.Close(); this._Validator.CacheStream = Stream.Null; } if (this._Validator.StrictCacheErrors) { this._Validator.CacheStream = this._RequestCache.Retrieve(this._Validator.CacheKey, out entry); } else { Stream stream; this._RequestCache.TryRetrieve(this._Validator.CacheKey, out entry, out stream); this._Validator.CacheStream = stream; } if (entry == null) { entry = new RequestCacheEntry { IsPrivateEntry = this._RequestCache.IsPrivateCache }; this._Validator.FetchCacheEntry(entry); } if (this._Validator.CacheStream == null) { this._Validator.CacheStream = Stream.Null; } this.ValidateFreshness(entry); this._ProtocolStatus = this.ValidateCache(); switch (this._ProtocolStatus) { case CacheValidationStatus.DoNotUseCache: case CacheValidationStatus.DoNotTakeFromCache: return; case CacheValidationStatus.Fail: this._ProtocolException = new InvalidOperationException(SR.GetString("net_cache_validator_fail", new object[] { "ValidateCache" })); return; case CacheValidationStatus.RetryResponseFromCache: goto Label_0000; case CacheValidationStatus.ReturnCachedResponse: if ((this._Validator.CacheStream != null) && (this._Validator.CacheStream != Stream.Null)) { break; } if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString("net_log_cache_no_cache_entry", new object[] { "ValidateCache()" })); } this._ProtocolStatus = CacheValidationStatus.Fail; this._ProtocolException = new InvalidOperationException(SR.GetString("net_cache_no_stream", new object[] { this._Validator.CacheKey })); return; case CacheValidationStatus.Continue: this._ResponseStream = this._Validator.CacheStream; return; default: goto Label_02CB; } Stream cacheStream = this._Validator.CacheStream; this._RequestCache.UnlockEntry(this._Validator.CacheStream); if ((this._Validator.CacheStreamOffset != 0L) || (this._Validator.CacheStreamLength != this._Validator.CacheEntry.StreamSize)) { cacheStream = new RangeStream(cacheStream, this._Validator.CacheStreamOffset, this._Validator.CacheStreamLength); if (Logging.On) { Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_returned_range_cache", new object[] { "ValidateCache()", this._Validator.CacheStreamOffset, this._Validator.CacheStreamLength })); } } this._ResponseStream = cacheStream; this._ResponseStreamLength = this._Validator.CacheStreamLength; return; Label_02CB: this._ProtocolStatus = CacheValidationStatus.Fail; this._ProtocolException = new InvalidOperationException(SR.GetString("net_cache_validator_result", new object[] { "ValidateCache", this._Validator.ValidationStatus.ToString() })); if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString("net_log_cache_unexpected_status", new object[] { "ValidateCache()", this._Validator.ValidationStatus.ToString() })); } } catch (Exception exception) { this._ProtocolStatus = CacheValidationStatus.Fail; this._ProtocolException = exception; if (((exception is ThreadAbortException) || (exception is StackOverflowException)) || (exception is OutOfMemoryException)) { throw; } if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString("net_log_cache_object_and_exception", new object[] { "CacheProtocol#" + this.GetHashCode().ToString(NumberFormatInfo.InvariantInfo), (exception is WebException) ? exception.Message : exception.ToString() })); } } finally { if (((this._ResponseStream == null) && (this._Validator.CacheStream != null)) && (this._Validator.CacheStream != Stream.Null)) { this._Validator.CacheStream.Close(); this._Validator.CacheStream = Stream.Null; } } }
// Returns a read data stream and metadata associated with a cached entry. // Returns Stream.Null if there is no entry found. // <remarks> An opened cache entry be preserved until the stream is closed. </remarks> // internal abstract Stream Retrieve(string key, out RequestCacheEntry cacheEntry);
// // Private methods // // // This method may be invoked as part of the request submission but before issuing a live request // private void CheckRetrieveBeforeSubmit() { GlobalLog.Assert(_ProtocolStatus == CacheValidationStatus.Continue, "CheckRetrieveBeforeSubmit()|Unexpected _ProtocolStatus = {0}", _ProtocolStatus); try { while (true) { RequestCacheEntry cacheEntry; if (_Validator.CacheStream != null && _Validator.CacheStream != Stream.Null) { // Reset to Initial state _Validator.CacheStream.Close(); _Validator.CacheStream = Stream.Null; } if (_Validator.StrictCacheErrors) { _Validator.CacheStream = _RequestCache.Retrieve(_Validator.CacheKey, out cacheEntry); } else { Stream stream; _RequestCache.TryRetrieve(_Validator.CacheKey, out cacheEntry, out stream); _Validator.CacheStream = stream; } if (cacheEntry == null) { cacheEntry = new RequestCacheEntry(); cacheEntry.IsPrivateEntry = _RequestCache.IsPrivateCache; _Validator.FetchCacheEntry(cacheEntry); } if (_Validator.CacheStream == null) { // If entry does not have a stream an empty stream wrapper must be returned. // A null or Stream.Null value stands for non existent cache entry. _Validator.CacheStream = Stream.Null; } ValidateFreshness(cacheEntry); _ProtocolStatus = ValidateCache(); // This will tell us what to do next switch (_ProtocolStatus) { case CacheValidationStatus.ReturnCachedResponse: if (_Validator.CacheStream == null || _Validator.CacheStream == Stream.Null) { if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_no_cache_entry, "ValidateCache()")); } _ProtocolStatus = CacheValidationStatus.Fail; _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_no_stream, _Validator.CacheKey)); break; } // Final decision is made, check on a range response from cache Stream stream = _Validator.CacheStream; // The entry can now be replaced as we are not going for cache entry metadata-only update _RequestCache.UnlockEntry(_Validator.CacheStream); if (_Validator.CacheStreamOffset != 0L || _Validator.CacheStreamLength != _Validator.CacheEntry.StreamSize) { stream = new RangeStream(stream, _Validator.CacheStreamOffset, _Validator.CacheStreamLength); if (Logging.On) { Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_returned_range_cache, "ValidateCache()", _Validator.CacheStreamOffset, _Validator.CacheStreamLength)); } } _ResponseStream = stream; _ResponseStreamLength = _Validator.CacheStreamLength; break; case CacheValidationStatus.Continue: // copy a cache stream ref _ResponseStream = _Validator.CacheStream; break; case CacheValidationStatus.RetryResponseFromCache: // loop thought cache retrieve continue; case CacheValidationStatus.DoNotTakeFromCache: case CacheValidationStatus.DoNotUseCache: break; case CacheValidationStatus.Fail: _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_validator_fail, "ValidateCache")); break; default: _ProtocolStatus = CacheValidationStatus.Fail; _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_validator_result, "ValidateCache", _Validator.ValidationStatus.ToString())); if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_unexpected_status, "ValidateCache()", _Validator.ValidationStatus.ToString())); } break; } break; } } catch (Exception e) { _ProtocolStatus = CacheValidationStatus.Fail; _ProtocolException = e; if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) { throw; } if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_object_and_exception, "CacheProtocol#" + this.GetHashCode().ToString(NumberFormatInfo.InvariantInfo), (e is WebException? e.Message: e.ToString()))); } } finally { // This is to release cache entry on error if (_ResponseStream == null && _Validator.CacheStream != null && _Validator.CacheStream != Stream.Null) { _Validator.CacheStream.Close(); _Validator.CacheStream = Stream.Null; } } }
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; writeStream = new WriteOnlyStream(key, this, requestCacheEntry, realWriteStream); return true; }
private void CheckUpdateOnResponse(Stream responseStream) { if (this._Validator.CacheEntry == null) { RequestCacheEntry fetchEntry = new RequestCacheEntry { IsPrivateEntry = this._RequestCache.IsPrivateCache }; this._Validator.FetchCacheEntry(fetchEntry); } string cacheKey = this._Validator.CacheKey; bool flag = true; try { Stream stream; switch ((this._ProtocolStatus = this.UpdateCache())) { case CacheValidationStatus.DoNotUseCache: case CacheValidationStatus.DoNotUpdateCache: return; case CacheValidationStatus.Fail: this._ProtocolException = new InvalidOperationException(SR.GetString("net_cache_validator_fail", new object[] { "UpdateCache" })); return; case CacheValidationStatus.CacheResponse: if (!this._Validator.StrictCacheErrors) { break; } stream = this._RequestCache.Store(this._Validator.CacheKey, this._Validator.CacheEntry.StreamSize, this._Validator.CacheEntry.ExpiresUtc, this._Validator.CacheEntry.LastModifiedUtc, this._Validator.CacheEntry.MaxStale, this._Validator.CacheEntry.EntryMetadata, this._Validator.CacheEntry.SystemMetadata); goto Label_022C; case CacheValidationStatus.UpdateResponseInformation: this._ResponseStream = new MetadataUpdateStream(responseStream, this._RequestCache, this._Validator.CacheKey, this._Validator.CacheEntry.ExpiresUtc, this._Validator.CacheEntry.LastModifiedUtc, this._Validator.CacheEntry.LastSynchronizedUtc, this._Validator.CacheEntry.MaxStale, this._Validator.CacheEntry.EntryMetadata, this._Validator.CacheEntry.SystemMetadata, this._Validator.StrictCacheErrors); flag = false; this._ProtocolStatus = CacheValidationStatus.UpdateResponseInformation; return; case CacheValidationStatus.RemoveFromCache: this.EnsureCacheRemoval(cacheKey); flag = false; return; default: goto Label_0298; } this._RequestCache.TryStore(this._Validator.CacheKey, this._Validator.CacheEntry.StreamSize, this._Validator.CacheEntry.ExpiresUtc, this._Validator.CacheEntry.LastModifiedUtc, this._Validator.CacheEntry.MaxStale, this._Validator.CacheEntry.EntryMetadata, this._Validator.CacheEntry.SystemMetadata, out stream); Label_022C: if (stream == null) { this._ProtocolStatus = CacheValidationStatus.DoNotUpdateCache; } else { this._ResponseStream = new ForwardingReadStream(responseStream, stream, this._Validator.CacheStreamOffset, this._Validator.StrictCacheErrors); this._ProtocolStatus = CacheValidationStatus.UpdateResponseInformation; } return; Label_0298: this._ProtocolStatus = CacheValidationStatus.Fail; this._ProtocolException = new InvalidOperationException(SR.GetString("net_cache_validator_result", new object[] { "UpdateCache", this._Validator.ValidationStatus.ToString() })); if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString("net_log_cache_unexpected_status", new object[] { "UpdateCache()", this._Validator.ValidationStatus.ToString() })); } } finally { if (flag) { this._RequestCache.UnlockEntry(this._Validator.CacheStream); } } }
private void Commit(string key, RequestCacheEntry tempEntry, byte[] allBytes) { FrozenCacheEntry entry = new FrozenCacheEntry(key, tempEntry, allBytes); this._Entry = entry; }
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 cacheEntry = new RequestCacheEntry { IsPrivateEntry = base.IsPrivateCache, StreamSize = contentLength, ExpiresUtc = expiresUtc, LastModifiedUtc = lastModifiedUtc, LastAccessedUtc = DateTime.UtcNow, LastSynchronizedUtc = DateTime.UtcNow, MaxStale = maxStale, HitCount = 0, UsageCount = 0, IsPartialEntry = false, EntryMetadata = entryMetadata, SystemMetadata = systemMetadata }; writeStream = null; Stream stream = null; if (this._UseWinInet) { base.TryStore(key, contentLength, expiresUtc, lastModifiedUtc, maxStale, entryMetadata, systemMetadata, out stream); } writeStream = new WriteOnlyStream(key, this, cacheEntry, stream); return true; }
// Returns a read data stream and metadata associated with a cached entry. // Returns Stream.Null if there is no entry found. // <remarks> An opened cache entry be preserved until the stream is closed. </remarks> // 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; }
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) { return false; } cacheEntry = FrozenCacheEntry.Create(chkEntry); readStream = new ReadOnlyStream(chkEntry.StreamBytes); return true; }
public FrozenCacheEntry(string key, RequestCacheEntry entry, Stream stream): this(key, entry, GetBytes(stream)) { }
// internal void FetchCacheEntry(RequestCacheEntry fetchEntry) { _CacheEntry = fetchEntry; }
// // // private Stream Lookup(string key, out RequestCacheEntry cacheEntry, bool isThrow) { if(Logging.On) Logging.Enter(Logging.RequestCache, "WinInetCache.Retrieve", "key = " + key); if (key == null) { throw new ArgumentNullException("key"); } Stream result = Stream.Null; SafeUnlockUrlCacheEntryFile handle = null; _WinInetCache.Entry entry = new _WinInetCache.Entry(key, _MaximumResponseHeadersLength); try { handle = _WinInetCache.LookupFile(entry); if (entry.Error == _WinInetCache.Status.Success) { if(Logging.On) Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_filename, "WinInetCache.Retrieve()", entry.Filename, entry.Error)); cacheEntry = new RequestCacheEntry(entry, IsPrivateCache); if (entry.MetaInfo != null && entry.MetaInfo.Length != 0) { // convert metadata to upto two string collections unsafe { int start = 0; int length = entry.MetaInfo.Length; StringCollection sc = new StringCollection(); fixed (char * ch = entry.MetaInfo) { int i; for (i = 0; i < length; ++i) { // WinInet specific block!! // The point here is that wininet scans for ~U: throughly with no regard to \r\n so we mimic the same behavior if (i == start && i+2 < length) { if (ch[i] == '~' && (ch[i+1] == 'U' || ch[i+1] == 'u') && ch[i+2] == ':') { //Security: don't report what the username is while(i < length && ch[++i] != '\n') {;} start = i+1; continue; } } // note a metadata entry must terminate with \r\n if ((i+1 == length) || (ch[i] == '\n')) { string value = entry.MetaInfo.Substring(start, (ch[i-1] == '\r'? (i-1):(i+1)) - start); if (value.Length == 0 && cacheEntry.EntryMetadata == null) { // done with headers, prepare for system metadata cacheEntry.EntryMetadata = sc; sc = new StringCollection(); } else { //WinInet specific block!! // HACK: if we are parsing system metadata and have found our hack, // then convert it to a sparse entry type (entry.Info.EntryType & _WinInetCache.EntryType.Sparse) if (cacheEntry.EntryMetadata != null && value.StartsWith(c_SPARSE_ENTRY_HACK, StringComparison.Ordinal)) cacheEntry.IsPartialEntry = true; else sc.Add(value); } start = i+1; } } } if (cacheEntry.EntryMetadata == null ) {cacheEntry.EntryMetadata = sc;} else {cacheEntry.SystemMetadata = sc;} } } result = new ReadStream(entry, handle, async); } else { if (handle != null) { handle.Close(); } cacheEntry = new RequestCacheEntry(); cacheEntry.IsPrivateEntry = IsPrivateCache; if (entry.Error != _WinInetCache.Status.FileNotFound) { if(Logging.On)Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_lookup_failed, "WinInetCache.Retrieve()", new Win32Exception((int)entry.Error).Message)); if(Logging.On)Logging.Exit(Logging.RequestCache, "WinInetCache.Retrieve()"); if(isThrow) { Win32Exception win32Exception = new Win32Exception((int)entry.Error); throw new IOException(SR.GetString(SR.net_cache_retrieve_failure, win32Exception.Message), win32Exception); } return null; } } } catch (Exception exception) { if (exception is ThreadAbortException || exception is StackOverflowException || exception is OutOfMemoryException) { throw; } if(Logging.On)Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_exception, "WinInetCache.Retrieve()", exception.ToString())); if(Logging.On)Logging.Exit(Logging.RequestCache, "WinInetCache.Retrieve()"); if (handle != null) { handle.Close(); } result.Close(); result = Stream.Null; cacheEntry = new RequestCacheEntry(); cacheEntry.IsPrivateEntry = IsPrivateCache; if (isThrow) { throw; } return null; } if(Logging.On)Logging.Exit(Logging.RequestCache, "WinInetCache.Retrieve()", "Status = " + entry.Error.ToString()); return result; }
// // Does not throw on failure internal abstract bool TryRetrieve(string key, out RequestCacheEntry cacheEntry, out Stream readStream);
// // This will decide on cache update and construct the effective response stream // private void CheckUpdateOnResponse(Stream responseStream) { if (_Validator.CacheEntry == null) { // There was no chance to create an empty entry yet RequestCacheEntry cacheEntry = new RequestCacheEntry(); cacheEntry.IsPrivateEntry = _RequestCache.IsPrivateCache; _Validator.FetchCacheEntry(cacheEntry); } // With NoCache we may end up storing whole response as a new entry in Cache. // Otherwise we may end up updating Context+Metadata or just Context // // In any case we may end up doing nothing. // string retrieveKey = _Validator.CacheKey; bool unlockEntry = true; try { switch (_ProtocolStatus=UpdateCache()) { case CacheValidationStatus.RemoveFromCache: EnsureCacheRemoval(retrieveKey); unlockEntry = false; break; case CacheValidationStatus.UpdateResponseInformation: // NB: Just invoked validator must have updated CacheEntry and transferred // ONLY allowed headers from the response to the Context.xxxMetadata member _ResponseStream = new MetadataUpdateStream( responseStream, _RequestCache, _Validator.CacheKey, _Validator.CacheEntry.ExpiresUtc, _Validator.CacheEntry.LastModifiedUtc, _Validator.CacheEntry.LastSynchronizedUtc, _Validator.CacheEntry.MaxStale, _Validator.CacheEntry.EntryMetadata, _Validator.CacheEntry.SystemMetadata, _Validator.StrictCacheErrors); // // This can be looked as a design hole since we have to keep the entry // locked for the case when we want to update that previously retrieved entry. // I think RequestCache contract should allow to detect that a new physical cache entry // does not match to the "entry being updated" and so to should ignore updates on replaced entries. // unlockEntry = false; _ProtocolStatus = CacheValidationStatus.UpdateResponseInformation; break; case CacheValidationStatus.CacheResponse: // NB: Just invoked validator must have updated CacheEntry and transferred // ONLY allowed headers from the response to the Context.xxxMetadata member Stream stream; if (_Validator.StrictCacheErrors) {stream = _RequestCache.Store(_Validator.CacheKey, _Validator.CacheEntry.StreamSize, _Validator.CacheEntry.ExpiresUtc, _Validator.CacheEntry.LastModifiedUtc, _Validator.CacheEntry.MaxStale, _Validator.CacheEntry.EntryMetadata, _Validator.CacheEntry.SystemMetadata);} else {_RequestCache.TryStore(_Validator.CacheKey, _Validator.CacheEntry.StreamSize, _Validator.CacheEntry.ExpiresUtc, _Validator.CacheEntry.LastModifiedUtc, _Validator.CacheEntry.MaxStale, _Validator.CacheEntry.EntryMetadata, _Validator.CacheEntry.SystemMetadata, out stream);} // Wrap the response stream into forwarding one if (stream == null) { _ProtocolStatus = CacheValidationStatus.DoNotUpdateCache; } else { _ResponseStream = new ForwardingReadStream(responseStream, stream, _Validator.CacheStreamOffset, _Validator.StrictCacheErrors); _ProtocolStatus = CacheValidationStatus.UpdateResponseInformation; } break; case CacheValidationStatus.DoNotUseCache: case CacheValidationStatus.DoNotUpdateCache: break; case CacheValidationStatus.Fail: _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_validator_fail, "UpdateCache")); break; default: _ProtocolStatus = CacheValidationStatus.Fail; _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_validator_result, "UpdateCache", _Validator.ValidationStatus.ToString())); if(Logging.On) Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_unexpected_status, "UpdateCache()", _Validator.ValidationStatus.ToString())); break; } } finally { if (unlockEntry) { // The entry can now be replaced as we are not going for cache entry metadata-only update _RequestCache.UnlockEntry(_Validator.CacheStream); } } }
// // This will decide on cache update and construct the effective response stream // private void CheckUpdateOnResponse(Stream responseStream) { if (_Validator.CacheEntry == null) { // There was no chance to create an empty entry yet RequestCacheEntry cacheEntry = new RequestCacheEntry(); cacheEntry.IsPrivateEntry = _RequestCache.IsPrivateCache; _Validator.FetchCacheEntry(cacheEntry); } // With NoCache we may end up storing whole response as a new entry in Cache. // Otherwise we may end up updating Context+Metadata or just Context // // In any case we may end up doing nothing. // string retrieveKey = _Validator.CacheKey; bool unlockEntry = true; try { switch (_ProtocolStatus = UpdateCache()) { case CacheValidationStatus.RemoveFromCache: EnsureCacheRemoval(retrieveKey); unlockEntry = false; break; case CacheValidationStatus.UpdateResponseInformation: // NB: Just invoked validator must have updated CacheEntry and transferred // ONLY allowed headers from the response to the Context.xxxMetadata member _ResponseStream = new MetadataUpdateStream( responseStream, _RequestCache, _Validator.CacheKey, _Validator.CacheEntry.ExpiresUtc, _Validator.CacheEntry.LastModifiedUtc, _Validator.CacheEntry.LastSynchronizedUtc, _Validator.CacheEntry.MaxStale, _Validator.CacheEntry.EntryMetadata, _Validator.CacheEntry.SystemMetadata, _Validator.StrictCacheErrors); // // This can be looked as a design hole since we have to keep the entry // locked for the case when we want to update that previously retrieved entry. // I think RequestCache contract should allow to detect that a new physical cache entry // does not match to the "entry being updated" and so to should ignore updates on replaced entries. // unlockEntry = false; _ProtocolStatus = CacheValidationStatus.UpdateResponseInformation; break; case CacheValidationStatus.CacheResponse: // NB: Just invoked validator must have updated CacheEntry and transferred // ONLY allowed headers from the response to the Context.xxxMetadata member Stream stream; if (_Validator.StrictCacheErrors) { stream = _RequestCache.Store(_Validator.CacheKey, _Validator.CacheEntry.StreamSize, _Validator.CacheEntry.ExpiresUtc, _Validator.CacheEntry.LastModifiedUtc, _Validator.CacheEntry.MaxStale, _Validator.CacheEntry.EntryMetadata, _Validator.CacheEntry.SystemMetadata); } else { _RequestCache.TryStore(_Validator.CacheKey, _Validator.CacheEntry.StreamSize, _Validator.CacheEntry.ExpiresUtc, _Validator.CacheEntry.LastModifiedUtc, _Validator.CacheEntry.MaxStale, _Validator.CacheEntry.EntryMetadata, _Validator.CacheEntry.SystemMetadata, out stream); } // Wrap the response stream into forwarding one _ResponseStream = new ForwardingReadStream(responseStream, stream, _Validator.CacheStreamOffset, _Validator.StrictCacheErrors); _ProtocolStatus = CacheValidationStatus.UpdateResponseInformation; break; case CacheValidationStatus.DoNotUseCache: case CacheValidationStatus.DoNotUpdateCache: break; case CacheValidationStatus.Fail: _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_validator_fail, "UpdateCache")); break; default: _ProtocolStatus = CacheValidationStatus.Fail; _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_validator_result, "UpdateCache", _Validator.ValidationStatus.ToString())); if (Logging.On) { Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_unexpected_status, "UpdateCache()", _Validator.ValidationStatus.ToString())); } break; } } finally { if (unlockEntry) { // The entry can now be replaced as we are not going for cache entry metadata-only update _RequestCache.UnlockEntry(_Validator.CacheStream); } } }
// // Private methods // // // This method may be invoked as part of the request submission but before issuing a live request // private void CheckRetrieveBeforeSubmit() { GlobalLog.Assert(_ProtocolStatus == CacheValidationStatus.Continue, "CheckRetrieveBeforeSubmit()|Unexpected _ProtocolStatus = {0}", _ProtocolStatus); try { while (true) { RequestCacheEntry cacheEntry; if (_Validator.CacheStream != null && _Validator.CacheStream != Stream.Null) { // Reset to Initial state _Validator.CacheStream.Close(); _Validator.CacheStream = Stream.Null; } if (_Validator.StrictCacheErrors) { _Validator.CacheStream = _RequestCache.Retrieve(_Validator.CacheKey, out cacheEntry); } else { Stream stream; _RequestCache.TryRetrieve(_Validator.CacheKey, out cacheEntry, out stream); _Validator.CacheStream = stream; } if (cacheEntry == null) { cacheEntry = new RequestCacheEntry(); cacheEntry.IsPrivateEntry = _RequestCache.IsPrivateCache; _Validator.FetchCacheEntry(cacheEntry); } if (_Validator.CacheStream == null) { // If entry does not have a stream an empty stream wrapper must be returned. // A null or Stream.Null value stands for non existent cache entry. _Validator.CacheStream = Stream.Null; } ValidateFreshness(cacheEntry); _ProtocolStatus = ValidateCache(); // This will tell us what to do next switch (_ProtocolStatus) { case CacheValidationStatus.ReturnCachedResponse: if (_Validator.CacheStream == null || _Validator.CacheStream == Stream.Null) { if(Logging.On) Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_no_cache_entry, "ValidateCache()")); _ProtocolStatus = CacheValidationStatus.Fail; _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_no_stream, _Validator.CacheKey)); break; } // Final decision is made, check on a range response from cache Stream stream = _Validator.CacheStream; // The entry can now be replaced as we are not going for cache entry metadata-only update _RequestCache.UnlockEntry(_Validator.CacheStream); if (_Validator.CacheStreamOffset != 0L || _Validator.CacheStreamLength != _Validator.CacheEntry.StreamSize) { stream = new RangeStream(stream, _Validator.CacheStreamOffset, _Validator.CacheStreamLength); if(Logging.On) Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_returned_range_cache, "ValidateCache()", _Validator.CacheStreamOffset, _Validator.CacheStreamLength)); } _ResponseStream = stream; _ResponseStreamLength = _Validator.CacheStreamLength; break; case CacheValidationStatus.Continue: // copy a cache stream ref _ResponseStream = _Validator.CacheStream; break; case CacheValidationStatus.RetryResponseFromCache: // loop thought cache retrieve continue; case CacheValidationStatus.DoNotTakeFromCache: case CacheValidationStatus.DoNotUseCache: break; case CacheValidationStatus.Fail: _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_validator_fail, "ValidateCache")); break; default: _ProtocolStatus = CacheValidationStatus.Fail; _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_validator_result, "ValidateCache", _Validator.ValidationStatus.ToString())); if(Logging.On) Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_unexpected_status, "ValidateCache()", _Validator.ValidationStatus.ToString())); break; } break; } } catch (Exception e) { _ProtocolStatus = CacheValidationStatus.Fail; _ProtocolException = e; if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) { throw; } if(Logging.On) Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_object_and_exception, "CacheProtocol#" + this.GetHashCode().ToString(NumberFormatInfo.InvariantInfo), (e is WebException? e.Message: e.ToString()))); } finally { // This is to release cache entry on error if (_ResponseStream == null && _Validator.CacheStream != null && _Validator.CacheStream != Stream.Null) { _Validator.CacheStream.Close(); _Validator.CacheStream = Stream.Null; } } }
// // // private void ValidateFreshness(RequestCacheEntry fetchEntry) { _Validator.FetchCacheEntry(fetchEntry); if (_Validator.CacheStream == null || _Validator.CacheStream == Stream.Null) { if(Logging.On) Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_entry_not_found_freshness_undefined, "ValidateFreshness()")); _Validator.SetFreshnessStatus(CacheFreshnessStatus.Undefined); return; } if(Logging.On) { if (Logging.IsVerbose(Logging.RequestCache)) { Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_dumping_cache_context)); if (fetchEntry == null) { Logging.PrintInfo(Logging.RequestCache, "<null>"); } else { string[] context = fetchEntry.ToString(Logging.IsVerbose(Logging.RequestCache)).Split(RequestCache.LineSplits); for (int i = 0; i< context.Length; ++i) { if (context[i].Length != 0) { Logging.PrintInfo(Logging.RequestCache, context[i]); } } } } } CacheFreshnessStatus result = _Validator.ValidateFreshness(); _Validator.SetFreshnessStatus(result); _IsCacheFresh = result == CacheFreshnessStatus.Fresh; if(Logging.On) Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_result, "ValidateFreshness()", result.ToString())); }