PageRenderTime 157ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/ABB.SrcML/LastModifiedArchive.cs

https://github.com/nkcsgexi/SrcML.NET
C# | 203 lines | 106 code | 25 blank | 72 comment | 7 complexity | 87312e8cb3c766d811d95f97070595c6 MD5 | raw file
  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Collections.Generic;
  4. using System.Collections.ObjectModel;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. namespace ABB.SrcML {
  10. /// <summary>
  11. /// The last modified archive simply stores the last-modified times of all its files.
  12. /// It serializes them to disk upon <see cref="LastModifiedArchive.Dispose()">disposal</see>
  13. /// </summary>
  14. public class LastModifiedArchive : AbstractArchive {
  15. //private Dictionary<string, DateTime> lastModifiedMap;
  16. private ConcurrentDictionary<string, DateTime> lastModifiedMap;
  17. private readonly object mapLock = new object();
  18. /// <summary>
  19. /// Creates a new archive in the <paramref name="baseDirectory">specified directory</paramref> with a default file name.
  20. /// </summary>
  21. /// <param name="baseDirectory"></param>
  22. public LastModifiedArchive(string baseDirectory)
  23. : this(baseDirectory, "lastmodifiedmap.txt") {
  24. }
  25. /// <summary>
  26. /// Creates a new archive in the <paramref name="baseDirectory">specified directory</paramref> with the given <paramref name="fileName"/>
  27. /// </summary>
  28. /// <param name="baseDirectory">the directory that this archive will be stored in</param>
  29. /// <param name="fileName">the filename to store the mapping in</param>
  30. public LastModifiedArchive(string baseDirectory, string fileName)
  31. : this(baseDirectory, fileName, TaskScheduler.Default) { }
  32. /// <summary>
  33. /// Creates a new archive in the <paramref name="baseDirectory">specified directory</paramref> with the given <paramref name="fileName"/>
  34. /// </summary>
  35. /// <param name="baseDirectory">the directory that this archive will be stored in</param>
  36. /// <param name="fileName">the filename to store the mapping in</param>
  37. /// <param name="scheduler">The task factory to use for asynchronous methods</param>
  38. public LastModifiedArchive(string baseDirectory, string fileName, TaskScheduler scheduler)
  39. : base(baseDirectory, fileName, scheduler) {
  40. lastModifiedMap = new ConcurrentDictionary<string, DateTime>(StringComparer.InvariantCultureIgnoreCase);
  41. ReadMap();
  42. }
  43. /// <summary>
  44. /// Returns a collection of all supported file extensions.
  45. /// </summary>
  46. public override ICollection<string> SupportedExtensions {
  47. get { throw new NotImplementedException(); }
  48. }
  49. /// <summary>
  50. /// Adds or updates <paramref name="fileName"/> to the archive. It raises <see cref="AbstractArchive.FileChanged"/> with
  51. /// <see cref="FileEventType.FileChanged"/> (if the file was in the archive) or <see cref="FileEventType.FileAdded"/>.
  52. /// </summary>
  53. /// <param name="fileName">The file name to add</param>
  54. protected override void AddOrUpdateFileImpl(string fileName) {
  55. string fullPath = GetFullPath(fileName);
  56. FileEventType eventType;
  57. eventType = (lastModifiedMap.ContainsKey(fullPath) ? FileEventType.FileChanged : FileEventType.FileAdded);
  58. lastModifiedMap[fullPath] = File.GetLastWriteTime(fullPath);
  59. OnFileChanged(new FileEventRaisedArgs(eventType, fullPath));
  60. }
  61. /// <summary>
  62. /// Deletes the given <paramref name="fileName"/> from the archive. It raises <see cref="AbstractArchive.FileChanged"/> with
  63. /// <see cref="FileEventType.FileDeleted"/> if the file was in the archive.
  64. /// </summary>
  65. /// <param name="fileName">The file to delete</param>
  66. protected override void DeleteFileImpl(string fileName) {
  67. string fullPath = GetFullPath(fileName);
  68. bool mapContainsFile = true;
  69. mapContainsFile = lastModifiedMap.ContainsKey(fullPath);
  70. DateTime result;
  71. if(lastModifiedMap.TryRemove(fullPath, out result)) {
  72. OnFileChanged(new FileEventRaisedArgs(FileEventType.FileDeleted, fullPath));
  73. }
  74. }
  75. /// <summary>
  76. /// Renames filename from <paramref name="oldFileName"/> to <paramref name="newFileName"/>. If <paramref name="oldFileName"/> is
  77. /// in the archive, then <see cref="AbstractArchive.FileChanged"/> is raised with <see cref="FileEventType.FileRenamed"/>. Otherwise, this method simply calls <see cref="AddOrUpdateFileImpl(string)"/>
  78. /// </summary>
  79. /// <param name="oldFileName">the old file path</param>
  80. /// <param name="newFileName">the new file path</param>
  81. protected override void RenameFileImpl(string oldFileName, string newFileName) {
  82. string oldFullPath = GetFullPath(oldFileName);
  83. string newFullPath = GetFullPath(newFileName);
  84. var eventType = FileEventType.FileAdded;
  85. DateTime result;
  86. if(lastModifiedMap.TryRemove(oldFullPath, out result)) {
  87. eventType = FileEventType.FileRenamed;
  88. }
  89. lastModifiedMap[newFullPath] = File.GetLastWriteTime(newFullPath);
  90. OnFileChanged(new FileEventRaisedArgs(eventType, newFullPath, oldFullPath));
  91. }
  92. /// <summary>
  93. /// Checks if the given file name is present in the archive
  94. /// </summary>
  95. /// <param name="fileName">The file name to test for</param>
  96. /// <returns>True if the file is in the archive; false otherwise</returns>
  97. public override bool ContainsFile(string fileName) {
  98. string fullPath = GetFullPath(fileName);
  99. lock(mapLock) {
  100. return lastModifiedMap.ContainsKey(fullPath);
  101. }
  102. }
  103. /// <summary>
  104. /// Checks if the archive is outdated in comparison to the original file. A file is outdated if any of the following are true:
  105. /// <list type="bullet">
  106. /// <item><description>the file does not exist and it is in the archive</description></item>
  107. /// <item><description>the file is not in the archive and it exists</description></item>
  108. /// <item><description>The last modified time in the archive is more recent than <paramref name="fileName"/></description></item>
  109. /// </list>
  110. /// </summary>
  111. /// <param name="fileName">the file to check</param>
  112. /// <returns>True if the file is outdated; false otherwise</returns>
  113. public override bool IsOutdated(string fileName) {
  114. string fullPath = GetFullPath(fileName);
  115. bool fileNameExists = File.Exists(fullPath);
  116. bool fileIsInArchive;
  117. DateTime lastModified = (fileNameExists ? File.GetLastWriteTime(fullPath) : DateTime.MinValue);
  118. DateTime lastModifiedInArchive;
  119. fileIsInArchive = this.lastModifiedMap.TryGetValue(fullPath, out lastModifiedInArchive);
  120. if(!fileIsInArchive) {
  121. lastModifiedInArchive = DateTime.MinValue;
  122. }
  123. return !(fileNameExists == fileIsInArchive && lastModified <= lastModifiedInArchive);
  124. }
  125. /// <summary>
  126. /// Gets all of the files stored in the archive
  127. /// </summary>
  128. /// <returns>the files in the archive</returns>
  129. public override Collection<string> GetFiles() {
  130. Collection<string> fileNames = new Collection<string>();
  131. lock(mapLock) {
  132. foreach(var fileName in lastModifiedMap.Keys) {
  133. fileNames.Add(fileName);
  134. }
  135. }
  136. return fileNames;
  137. }
  138. /// <summary>
  139. /// saves this archive to disk
  140. /// </summary>
  141. public override void Dispose() {
  142. SaveMap();
  143. base.Dispose();
  144. }
  145. /// <summary>
  146. /// Loads this map from disk (assuming <see cref="AbstractArchive.ArchivePath"/> exists)
  147. /// </summary>
  148. public void ReadMap() {
  149. if(File.Exists(this.ArchivePath)) {
  150. foreach(var line in File.ReadLines(this.ArchivePath)) {
  151. var parts = line.Split('|');
  152. this.lastModifiedMap[parts[0]] = new DateTime(Int64.Parse(parts[1]));
  153. }
  154. }
  155. }
  156. /// <summary>
  157. /// Saves this map to disk (at <see cref="AbstractArchive.ArchivePath"/>
  158. /// </summary>
  159. public void SaveMap() {
  160. if(File.Exists(this.ArchivePath)) {
  161. File.Delete(this.ArchivePath);
  162. }
  163. using(var output = File.CreateText(this.ArchivePath)) {
  164. foreach(var kvp in lastModifiedMap) {
  165. output.WriteLine("{0}|{1}", kvp.Key, kvp.Value.Ticks);
  166. }
  167. }
  168. }
  169. /// <summary>
  170. /// Gets the full path for a file name (returns the file name if <see cref="Path.IsPathRooted(string)"/> is true.
  171. /// </summary>
  172. /// <param name="fileName"></param>
  173. /// <returns></returns>
  174. private string GetFullPath(string fileName) {
  175. return (Path.IsPathRooted(fileName) ? fileName : Path.GetFullPath(fileName));
  176. }
  177. }
  178. }