void FinishOrCancelCapture(HttpResponse response, bool cancel) { if (_capturingResponse != response) { return; } if (_capturingFilter == null) { throw new InvalidOperationException("Response capturing filter is missing."); } lock (this) { try { _capturingFilter.StopFiltering(cancel); if (!cancel) { // remember the captured response string tempFilename = _capturingFilter.CaptureFilename; _infoFilename = tempFilename.Replace(TempFileExt, InfoFileExt); _dataFilename = tempFilename.Replace(TempFileExt, DataFileExt); DateTime timestamp = DateTime.UtcNow; _cachedResponseHash = CalculateHandlerHash(_path); _cachedResponseExpiry = timestamp + _duration; _nextResponseValidationTime = timestamp + HttpModule.OutputCache.FileValidationDelay; // save info file string info = string.Format( "<{0} path=\"{1}\" vary=\"{2}\" timestamp=\"{3}\" expiry=\"{4}\" hash=\"{5}\" />", InfoTagName, _path, _varyById, timestamp.ToBinary(), _cachedResponseExpiry.ToBinary(), _cachedResponseHash); File.WriteAllText(_infoFilename, info, Encoding.UTF8); // rename temp file into data file File.Move(tempFilename, _dataFilename); // read the data into memory if needed _cachedResponseBytes = new byte[0]; if (_serveFromMemory) { _cachedResponseBytes = File.ReadAllBytes(_dataFilename); } // now everything's ready _cachedResponseLoaded = true; } } finally { // notify any waiting threads that capturing is complete _capturingFilter = null; _capturingResponse = null; _capturingEvent.Set(); } } }
void FinishOrCancelCapture(HttpResponse response, bool cancel) { if (_capturingResponse != response) { return; } if (_capturingFilter == null) { throw new InvalidOperationException("Response capturing filter is missing."); } lock (this) { try { _capturingFilter.StopFiltering(cancel); if (!cancel) { // remember the captured response string tempFilename = _capturingFilter.CaptureFilename; _infoFilename = tempFilename.Replace(TempFileExt, InfoFileExt); _dataFilename = tempFilename.Replace(TempFileExt, DataFileExt); DateTime timestamp = DateTime.UtcNow; _cachedResponseHash = CalculateHandlerHash(_path); _cachedResponseExpiry = timestamp + _duration; _nextResponseValidationTime = timestamp + HttpModule.OutputCache.FileValidationDelay; // save info file string info = string.Format( "<{0} path=\"{1}\" vary=\"{2}\" timestamp=\"{3}\" expiry=\"{4}\" hash=\"{5}\" />", InfoTagName, _path, _varyById, timestamp.ToBinary(), _cachedResponseExpiry.ToBinary(), _cachedResponseHash); File.WriteAllText(_infoFilename, info, Encoding.UTF8); // rename temp file into data file File.Move(tempFilename, _dataFilename); // read the data into memory if needed _cachedResponseBytes = new byte[0]; if (_serveFromMemory) { _cachedResponseBytes = File.ReadAllBytes(_dataFilename); } // now everything's ready _cachedResponseLoaded = true; } } finally { // notify any waiting threads that capturing is complete _capturingFilter = null; _capturingResponse = null; _capturingEvent.Set(); } } }
public bool TrySendResponseOrStartResponseCapture(HttpResponse response) { byte[] responseData = null; string responseFile = null; // loop while trying to either send or capture the response // (the loop is needed for cases when another thread does the capture) for (; ; ) { lock (this) { // attempt to find the cached response on disk (only once) if (!_triedToLoadCachedResponse) { LookForCachedResponseOnDisk(); _triedToLoadCachedResponse = true; } if (_cachedResponseLoaded && ValidateLoadedCachedResponse()) { // serve the cached response if validated if (_serveFromMemory) { responseData = _cachedResponseBytes; } else { responseFile = _dataFilename; } // send the response outside of the lock break; } // couldn't send the response - try to capture it under lock // (don't attempt to capture the same response from 2 threads at the same time) if (_capturingResponse == null) { // generate new file name string filename = string.Format("{0}_{1:x8}{2}", _filenamePrefix, Guid.NewGuid().ToString().GetHashCode(), TempFileExt); _capturingFilter = new ResponseFilter(response.Filter, filename); response.Filter = _capturingFilter; // move the event - non-signaled state _capturingEvent.Reset(); // remember the response _capturingResponse = response; // started capturing - return from this method break; } } // capturing started from another thread - wait until done and continue (outside of the lock) _capturingEvent.WaitOne(); } // send the cached response if available (outside of the lock) if (responseData != null) { response.OutputStream.Write(responseData, 0, responseData.Length); return true; } else if (responseFile != null) { try { response.TransmitFile(responseFile); } catch { // if there is a problem sending data file, invalidate the cached response InvalidateCachedResponse(); throw; } return true; } else { return false; } }
public bool TrySendResponseOrStartResponseCapture(HttpResponse response) { byte[] responseData = null; string responseFile = null; // loop while trying to either send or capture the response // (the loop is needed for cases when another thread does the capture) for (; ;) { lock (this) { // attempt to find the cached response on disk (only once) if (!_triedToLoadCachedResponse) { LookForCachedResponseOnDisk(); _triedToLoadCachedResponse = true; } if (_cachedResponseLoaded && ValidateLoadedCachedResponse()) { // serve the cached response if validated if (_serveFromMemory) { responseData = _cachedResponseBytes; } else { responseFile = _dataFilename; } // send the response outside of the lock break; } // couldn't send the response - try to capture it under lock // (don't attempt to capture the same response from 2 threads at the same time) if (_capturingResponse == null) { // generate new file name string filename = string.Format("{0}_{1:x8}{2}", _filenamePrefix, Guid.NewGuid().ToString().GetHashCode(), TempFileExt); _capturingFilter = new ResponseFilter(response.Filter, filename); response.Filter = _capturingFilter; // move the event - non-signaled state _capturingEvent.Reset(); // remember the response _capturingResponse = response; // started capturing - return from this method break; } } // capturing started from another thread - wait until done and continue (outside of the lock) _capturingEvent.WaitOne(); } // send the cached response if available (outside of the lock) if (responseData != null) { response.OutputStream.Write(responseData, 0, responseData.Length); return(true); } else if (responseFile != null) { try { response.TransmitFile(responseFile); } catch { // if there is a problem sending data file, invalidate the cached response InvalidateCachedResponse(); throw; } return(true); } else { return(false); } }