/// <summary> /// Saves a particular RSS feed. /// </summary> /// <remarks>This method should be thread-safe</remarks> /// <param name="feed">The feed to save. This is an identifier /// and not used to actually fetch the feed from the WWW.</param> /// <returns>An identifier for the saved feed. </returns> public override string SaveFeed(IInternalFeedDetails feed) { string feedLocation = feed.FeedLocation; lock (this) { if (string.IsNullOrEmpty(feed.FeedLocation)) { feed.FeedLocation = feedLocation = GetCacheUrlName(feed.Id, new Uri(feed.Link)); } } //get location of binary file containing RSS item contents string feedContentLocation = feedLocation.Substring(0, feedLocation.Length - 4) + ".bin"; //write main RSS feed var tempFile = Path.GetTempFileName(); using (FileStream stream = FileHelper.OpenForWrite(tempFile)) { XmlTextWriter writer = new XmlTextWriter(new StreamWriter(stream)); feed.WriteTo(writer, true); writer.Flush(); } FileHelper.MoveFile(tempFile, Path.Combine(CacheLocation, feedLocation), MoveFileFlag.ReplaceExisting); //write binary file containing RSS item contents tempFile = Path.GetTempFileName(); using (FileStream stream = FileHelper.OpenForWrite(tempFile)) { var writer = new BinaryWriter(stream); FileStream fs = null; BinaryReader reader = null; try { if (File.Exists(Path.Combine(CacheLocation, feedContentLocation))) { fs = new FileStream(Path.Combine(CacheLocation, feedContentLocation), FileMode.OpenOrCreate); reader = new BinaryReader(fs); } feed.WriteItemContents(reader, writer); writer.Write(FileHelper.EndOfBinaryFileMarker); writer.Flush(); } finally { if (fs != null) { fs.Close(); } } } //using(...) FileHelper.MoveFile(tempFile, Path.Combine(CacheLocation, feedContentLocation), MoveFileFlag.ReplaceExisting); return(feedLocation); }
/// <summary> /// Returns an RSS feed. /// </summary> /// <param name="feed">The feed whose FeedInfo is required.</param> /// <returns>The requested feed or null if it doesn't exist</returns> public override IInternalFeedDetails GetFeed(INewsFeed feed) { if (null == feed || null == feed.cacheurl) { return(null); } IInternalFeedDetails fi = null; string cachelocation = Path.Combine(CacheLocation, feed.cacheurl); if (File.Exists(cachelocation)) { using (Stream feedStream = FileHelper.OpenForRead(cachelocation)) { fi = RssParser.GetItemsForFeed(feed, feedStream, true); } this.LoadItemContent(fi); } return(fi); }
/// <summary> /// Saves a particular RSS feed. /// </summary> /// <remarks>This method should be thread-safe</remarks> /// <param name="feed">The feed to save. This is an identifier /// and not used to actually fetch the feed from the WWW.</param> /// <returns>The feed ID</returns> public abstract string SaveFeed(IInternalFeedDetails feed);
/// <summary> /// Loads the content of the unread NewsItems from the binary file /// where item contents are contained. This is a memory-saving performance /// optimization so we only have the content of items that are unread on load. /// </summary> /// <param name="fi"></param> private void LoadItemContent(IInternalFeedDetails fi) { if (fi == null) { return; } Hashtable unreadItems = new Hashtable(); FileStream fs = null; BinaryReader reader = null; //get list of unread items foreach (NewsItem item in fi.ItemsList) { if (!item.BeenRead) { try { unreadItems.Add(item.Id, item); } catch (ArgumentException) { /* we don't test using ContainsKey() before Add() for performance reasons */ } } } try { string feedContentLocation = fi.FeedLocation.Substring(0, fi.FeedLocation.Length - 4) + ".bin"; string fileName = Path.Combine(CacheLocation, feedContentLocation); if (File.Exists(fileName)) { fs = FileHelper.OpenForRead(fileName); reader = new BinaryReader(fs); string id = reader.ReadString(); while (!string.IsNullOrEmpty(id) && !id.Equals(FileHelper.EndOfBinaryFileMarker)) { int count = reader.ReadInt32(); byte[] content = reader.ReadBytes(count); if (unreadItems.Contains(id)) { NewsItem ni = (NewsItem)unreadItems[id]; ni.SetContent(content, ContentType.Html); } id = reader.ReadString(); } //while(!id.Equals(...)) } } finally { if (fs != null) { fs.Close(); } } }