/// <summary> /// Updates a cache item in the database. Throws an exception if anything goes wrong. /// /// databaseContext.SaveChanges() still needs to be called. /// </summary> /// <param name="existingCacheItem">The existing global cache item.</param> /// <param name="headers">the new headers</param> /// <param name="statusCode">The new status code.</param> /// <param name="fileSize">The file size.</param> /// <param name="databaseContext">The database context.</param> private void UpdateCacheItemInDatabase(GlobalCacheItem existingCacheItem, NameValueCollection headers, short statusCode, long fileSize, RCDatabaseEntities databaseContext) { string headersJson = JsonConvert.SerializeObject(headers, Formatting.None, new NameValueCollectionConverter()); _proxy.Logger.Debug("Updating in database: " + existingCacheItem.filename); // Update non-RC data existingCacheItem.responseHeaders = headersJson; existingCacheItem.statusCode = statusCode; existingCacheItem.filesize = fileSize; // Update RC data GlobalCacheRCData rcData = existingCacheItem.GlobalCacheRCData; // Although this is not really a request, we set the lastRequestTime to now rcData.lastRequestTime = DateTime.Now; // One request more rcData.numberOfRequests++; // Download time is the lastModified time of the file, if it already exists. Otherwise now rcData.downloadTime = File.Exists(_cachePath + existingCacheItem.filename) ? File.GetLastWriteTime(_cachePath + existingCacheItem.filename) : DateTime.Now; }
/// <summary> /// Adds a new cache item to the database. Throws an exception if anything goes wrong. /// /// databaseContext.SaveChanges() still needs to be called. /// </summary> /// <param name="filename">The filename.</param> /// <param name="headers">The headers.</param> /// <param name="statusCode">The status code.</param> /// <param name="fileSize">The file size.</param> /// <param name="addToIndex">Whether a text/html file should be added to the Lucene index.</param> /// <param name="databaseContext">The database context.</param> private void AddCacheItemToDatabase(string filename, NameValueCollection headers, short statusCode,long fileSize, bool addToIndex, RCDatabaseEntities databaseContext) { // We disable cookies for non-streamed requests headers.Remove("Set-Cookie"); string headersJson = JsonConvert.SerializeObject(headers, Formatting.None, new NameValueCollectionConverter()); _proxy.Logger.Debug("Adding to database: " + filename); // Check if the RC data still exists (this means the file has been cached previsouly and was evicted) GlobalCacheRCData rcData = GetGlobalCacheRCData(filename, databaseContext); if (rcData == null) { // create a new rc data item rcData = new GlobalCacheRCData(); // Save the rc values rcData.filename = filename; // Although this is not really a request, we set the lastRequestTime to now rcData.lastRequestTime = DateTime.Now; // One requests so far rcData.numberOfRequests = 1; // Download time is the lastModified time of the file, if it already exists. Otherwise now rcData.downloadTime = File.Exists(_cachePath + filename) ? File.GetLastWriteTime(_cachePath + filename) : DateTime.Now; // add item databaseContext.GlobalCacheRCData.Add(rcData); } else { // Update RC data // Although this is not really a request, we set the lastRequestTime to now rcData.lastRequestTime = DateTime.Now; // One request more rcData.numberOfRequests++; // Download time is the lastModified time of the file, if it already exists. Otherwise now rcData.downloadTime = File.Exists(_cachePath + filename) ? File.GetLastWriteTime(_cachePath + filename) : DateTime.Now; } // Create item and save the values. GlobalCacheItem cacheItem = new GlobalCacheItem(); cacheItem.responseHeaders = headersJson; cacheItem.statusCode = statusCode; cacheItem.filename = filename; cacheItem.filesize = fileSize; // add item databaseContext.GlobalCacheItem.Add(cacheItem); // If we're on the local proxy, we want to add text documents to the Lucene index. if (addToIndex && _proxy is RCLocalProxy && GetHTTPMethodFromRelCacheFileName(filename).Equals("GET") && (headers["Content-Type"].Contains("text/html") || headers["Content-Type"].Contains("text/plain"))) { RCLocalProxy proxy = ((RCLocalProxy)_proxy); // The index might not have been initialized... if (proxy.IndexWrapper == null) { // FIXME We should not use the Program var here. // But when we're creating the DB, this gets called in the RCProxy constructor // before the RCLocalProxy constructor. We should find a way to have the index created // before the cache for the LP proxy.IndexWrapper = new IndexWrapper(Program.INDEX_PATH); // initialize the index proxy.IndexWrapper.EnsureIndexExists(); } // We have made sure the content-type header is always present in the DB! // XXX reading the file we just wrote. Not perfect. string document = Utils.ReadFileAsString(_cachePath + filename); string title = HtmlUtils.GetPageTitleFromHTML(document); // Use whole document, so we can also find results with tags, etc. try { proxy.Logger.Debug("Adding to index: " + filename); proxy.IndexWrapper.IndexDocument(FilePathToUri(filename), title, document); } catch (Exception e) { _proxy.Logger.Warn("Could not add document to index.", e); } } }
/// <summary> /// Removes a cache item and deletes the file. This method is used internally, when evicting. /// </summary> /// <param name="cacheItem">The cache item.</param> /// <param name="databaseContext">The database context.</param> private void RemoveCacheItem(GlobalCacheItem cacheItem, RCDatabaseEntities databaseContext) { _proxy.Logger.Debug(String.Format("Removing from the cache: {0} Last request: {1}", cacheItem.filename, cacheItem.GlobalCacheRCData.lastRequestTime)); // Remove file Utils.DeleteFile(_cachePath + cacheItem.filename); // Remove cache item entry databaseContext.GlobalCacheItem.Remove(cacheItem); // If we're on the local proxy, we want to remove text documents from the Lucene index. if (_proxy is RCLocalProxy && GetHTTPMethodFromRelCacheFileName(cacheItem.filename).Equals("GET") && (cacheItem.responseHeaders.Contains("\"Content-Type\":[\"text/html") || cacheItem.responseHeaders.Contains("\"Content-Type\":[\"text/plain"))) { try { // remove the file from Lucene, if it is a GET text or HTML file. // We have made sure the content-type header is always present in the DB! ((RCLocalProxy)_proxy).IndexWrapper.DeleteDocument(FilePathToUri(cacheItem.filename)); } catch (Exception e) { _proxy.Logger.Warn("Could not remove document from the index.", e); } } }