//
// 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);
}
}
}