PageRenderTime 34ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/R-Tree Framework v1/R-Tree Framework/LRU Cache Manager/LRUCache.cs

http://r-tree-csharp-framework.googlecode.com/
C# | 361 lines | 347 code | 14 blank | 0 comment | 42 complexity | 37ec8f019a119374b4a8771769458c8a MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using Edu.Psu.Cse.R_Tree_Framework.Framework;
  5. using System.IO;
  6. namespace Edu.Psu.Cse.R_Tree_Framework.CacheManagers
  7. {
  8. public class LRUCacheManager : CacheManager
  9. {
  10. #region Events
  11. public event CacheEventHandler PageFault;
  12. public event CacheEventHandler PageWrite;
  13. #endregion
  14. #region Instance Variables
  15. protected Boolean disablePageFault;
  16. protected Int32 cacheSize, numberOfNodes;
  17. protected Int64 nextPageAddress, ticks;
  18. protected String storageFileLocation;
  19. protected FileStream storageReader;
  20. protected List<Page> dirtyPages;
  21. protected Queue<Int64> freePages;
  22. protected Dictionary<Int64, Page> pageTranslationTable;
  23. protected SortedList<Int64, Page> leastRecentlyUsed;
  24. protected SortedDictionary<Address, Int64> addressTranslationTable;
  25. #endregion
  26. #region Properties
  27. protected virtual Int32 CachePercentage
  28. {
  29. get { return cacheSize; }
  30. }
  31. protected virtual SortedDictionary<Address, Int64> AddressTranslationTable
  32. {
  33. get { return addressTranslationTable; }
  34. set { addressTranslationTable = value; }
  35. }
  36. protected virtual Int32 CacheSize
  37. {
  38. get
  39. {
  40. Int32 pages = cacheSize * NumberOfNodes / 100;
  41. if (pages > 0)
  42. return pages;
  43. else if (cacheSize > 0)
  44. return 1;
  45. else
  46. return 0;
  47. }
  48. set { cacheSize = value; }
  49. }
  50. protected virtual Int32 NumberOfNodes
  51. {
  52. get { return numberOfNodes; }
  53. set { numberOfNodes = value; }
  54. }
  55. protected virtual List<Page> DirtyPages
  56. {
  57. get { return dirtyPages; }
  58. set { dirtyPages = value; }
  59. }
  60. protected virtual Boolean DisablePageFault
  61. {
  62. get { return disablePageFault; }
  63. set { disablePageFault = value; }
  64. }
  65. protected virtual Queue<Int64> FreePages
  66. {
  67. get { return freePages; }
  68. set { freePages = value; }
  69. }
  70. protected virtual SortedList<Int64, Page> LeastRecentlyUsed
  71. {
  72. get { return leastRecentlyUsed; }
  73. set { leastRecentlyUsed = value; }
  74. }
  75. protected virtual Int64 NextPageAddress
  76. {
  77. get
  78. {
  79. Int64 address = nextPageAddress;
  80. nextPageAddress += Constants.PAGE_SIZE;
  81. return address;
  82. }
  83. set { nextPageAddress = value; }
  84. }
  85. protected virtual Dictionary<Int64, Page> PageTranslationTable
  86. {
  87. get { return pageTranslationTable; }
  88. set { pageTranslationTable = value; }
  89. }
  90. protected virtual String StorageFileLocation
  91. {
  92. get { return storageFileLocation; }
  93. set { storageFileLocation = value; }
  94. }
  95. protected virtual FileStream StorageReader
  96. {
  97. get { return storageReader; }
  98. set { storageReader = value; }
  99. }
  100. protected virtual Int64 Ticks
  101. {
  102. get { return ticks; }
  103. set { ticks = value; }
  104. }
  105. #endregion
  106. #region Constructors
  107. public LRUCacheManager(String storageFileLocation, Int32 numberOfPagesToCache)
  108. {
  109. StorageFileLocation = storageFileLocation;
  110. StorageReader = new FileStream(
  111. StorageFileLocation,
  112. FileMode.Create,
  113. FileAccess.ReadWrite,
  114. FileShare.None,
  115. 8,
  116. FileOptions.WriteThrough | FileOptions.RandomAccess);
  117. CacheSize = numberOfPagesToCache;
  118. NumberOfNodes = 0;
  119. AddressTranslationTable = new SortedDictionary<Address, Int64>();
  120. PageTranslationTable = new Dictionary<Int64, Page>();
  121. LeastRecentlyUsed = new SortedList<Int64, Page>();
  122. DirtyPages = new List<Page>();
  123. FreePages = new Queue<Int64>();
  124. Ticks = 0;
  125. }
  126. public LRUCacheManager(String savedLocation, String memoryRunLocation)
  127. {
  128. StreamReader reader = new StreamReader(savedLocation);
  129. StorageFileLocation = reader.ReadLine();
  130. File.Copy(StorageFileLocation, memoryRunLocation, true);
  131. StorageFileLocation = memoryRunLocation;
  132. NextPageAddress = Int64.Parse(reader.ReadLine());
  133. CacheSize = Int32.Parse(reader.ReadLine());
  134. NumberOfNodes = Int32.Parse(reader.ReadLine());
  135. StorageReader = new FileStream(
  136. memoryRunLocation,
  137. FileMode.OpenOrCreate,
  138. FileAccess.ReadWrite,
  139. FileShare.None,
  140. 8,
  141. FileOptions.WriteThrough | FileOptions.RandomAccess);
  142. AddressTranslationTable = new SortedDictionary<Address, Int64>();
  143. PageTranslationTable = new Dictionary<Int64, Page>();
  144. LeastRecentlyUsed = new SortedList<Int64, Page>();
  145. DirtyPages = new List<Page>();
  146. FreePages = new Queue<Int64>();
  147. Ticks = 0;
  148. if (!reader.ReadLine().Equals("AddressTranslationTable"))
  149. throw new Exception();
  150. String buffer;
  151. while (!(buffer = reader.ReadLine()).Equals("FreePages"))
  152. AddressTranslationTable.Add(
  153. new Address(buffer),
  154. Int64.Parse(reader.ReadLine()));
  155. while (!reader.EndOfStream)
  156. FreePages.Enqueue(Int64.Parse(reader.ReadLine()));
  157. reader.Close();
  158. }
  159. #endregion
  160. #region Public Methods
  161. public virtual void DeletePageData(PageData data)
  162. {
  163. if (!(data is Record))
  164. NumberOfNodes--;
  165. Int64 address = AddressTranslationTable[data.Address];
  166. AddressTranslationTable.Remove(data.Address);
  167. if (PageTranslationTable.ContainsKey(address))
  168. {
  169. Page page = PageTranslationTable[address];
  170. PageTranslationTable.Remove(address);
  171. LeastRecentlyUsed.RemoveAt(LeastRecentlyUsed.IndexOfValue(page));
  172. while (DirtyPages.Contains(page))
  173. DirtyPages.Remove(page);
  174. }
  175. FreePages.Enqueue(address);
  176. }
  177. public virtual void Dispose()
  178. {
  179. StorageReader.Close();
  180. File.Delete(StorageFileLocation);
  181. }
  182. public virtual void FlushCache()
  183. {
  184. while (PageTranslationTable.Count > 0)
  185. EvictPage();
  186. }
  187. public virtual Node LookupNode(Address address)
  188. {
  189. return LookupPageData(address) as Node;
  190. }
  191. public virtual Record LookupRecord(Address address)
  192. {
  193. DisablePageFault = true;
  194. Record record = LookupPageData(address) as Record;
  195. DisablePageFault = false;
  196. return record;
  197. }
  198. public virtual Sector LookupSector(Address address)
  199. {
  200. return LookupPageData(address) as Sector;
  201. }
  202. public virtual void SaveCache(String cacheSaveLocation, String memorySaveLocation)
  203. {
  204. FlushCache();
  205. Int64 position = StorageReader.Position;
  206. StorageReader.Close();
  207. File.Copy(StorageFileLocation, memorySaveLocation, true);
  208. StorageReader = new FileStream(
  209. StorageFileLocation,
  210. FileMode.Open,
  211. FileAccess.ReadWrite,
  212. FileShare.None,
  213. 8,
  214. FileOptions.WriteThrough | FileOptions.RandomAccess);
  215. StorageReader.Seek(position, SeekOrigin.Begin);
  216. StreamWriter writer = new StreamWriter(cacheSaveLocation);
  217. writer.WriteLine(memorySaveLocation);
  218. writer.WriteLine(NextPageAddress);
  219. writer.WriteLine(CachePercentage);
  220. writer.WriteLine(NumberOfNodes);
  221. writer.WriteLine("AddressTranslationTable");
  222. foreach (KeyValuePair<Address, Int64> entry in AddressTranslationTable)
  223. {
  224. writer.WriteLine(entry.Key);
  225. writer.WriteLine(entry.Value);
  226. }
  227. writer.WriteLine("FreePages");
  228. foreach (Int64 page in FreePages)
  229. writer.WriteLine(page);
  230. writer.Close();
  231. }
  232. public virtual void WritePageData(PageData data)
  233. {
  234. Page page;
  235. if (!AddressTranslationTable.ContainsKey(data.Address))
  236. {
  237. page = AllocateNewPage(data.Address);
  238. if (!(data is Record))
  239. NumberOfNodes++;
  240. }
  241. else
  242. {
  243. Int64 address = AddressTranslationTable[data.Address];
  244. if (PageTranslationTable.ContainsKey(address))
  245. page = PageTranslationTable[address];
  246. else
  247. {
  248. page = LoadPageFromMemory(address);
  249. PageTranslationTable.Add(page.Address, page);
  250. }
  251. }
  252. page.Data = data.GeneratePageData();
  253. DirtyPages.Add(page);
  254. if (LeastRecentlyUsed.ContainsValue(page))
  255. LeastRecentlyUsed.RemoveAt(LeastRecentlyUsed.IndexOfValue(page));
  256. LeastRecentlyUsed.Add(Ticks++, page);
  257. CacheOverflowCheck();
  258. }
  259. #endregion
  260. #region Protected Methods
  261. protected virtual Page AllocateNewPage(Address address)
  262. {
  263. Int64 pageAddress;
  264. if (FreePages.Count > 0)
  265. pageAddress = FreePages.Dequeue();
  266. else
  267. pageAddress = NextPageAddress;
  268. AddressTranslationTable.Add(address, pageAddress);
  269. Page newPage = new Page(Address.NewAddress(), pageAddress, new Byte[Constants.PAGE_SIZE]);
  270. PageTranslationTable.Add(pageAddress, newPage);
  271. return newPage;
  272. }
  273. protected virtual void CacheOverflowCheck()
  274. {
  275. while (PageTranslationTable.Count > CacheSize)
  276. EvictPage();
  277. }
  278. protected virtual void EvictPage()
  279. {
  280. Page page = leastRecentlyUsed[leastRecentlyUsed.Keys[0]];
  281. if (DirtyPages.Contains(page))
  282. WritePageToMemory(page);
  283. LeastRecentlyUsed.RemoveAt(0);
  284. while (DirtyPages.Contains(page))
  285. DirtyPages.Remove(page);
  286. PageTranslationTable.Remove(page.Address);
  287. }
  288. protected virtual Page LoadPageFromMemory(Int64 offset)
  289. {
  290. Byte[] data = new Byte[Constants.PAGE_SIZE];
  291. StorageReader.Seek(offset - offset % Constants.PAGE_SIZE, SeekOrigin.Begin);
  292. StorageReader.Read(data, 0, Constants.PAGE_SIZE);
  293. Page page = new Page(Address.NewAddress(), offset, data);
  294. if (PageFault != null && !DisablePageFault)
  295. PageFault(this, new LRUCacheEventArgs(page));
  296. return page;
  297. }
  298. protected virtual Page LookupPage(Address address)
  299. {
  300. Page page;
  301. Int64 offset = AddressTranslationTable[address];
  302. if (PageTranslationTable.ContainsKey(offset))
  303. {
  304. page = PageTranslationTable[offset];
  305. LeastRecentlyUsed.RemoveAt(LeastRecentlyUsed.IndexOfValue(page));
  306. }
  307. else
  308. {
  309. page = LoadPageFromMemory(offset);
  310. PageTranslationTable.Add(page.Address, page);
  311. }
  312. LeastRecentlyUsed.Add(Ticks++, page);
  313. return page;
  314. }
  315. protected virtual PageData LookupPageData(Address address)
  316. {
  317. PageData data;
  318. Page page = LookupPage(address);
  319. Byte type = page.Data[0], childType = page.Data[1];
  320. if (type == (Byte)PageDataType.Node || type == (Byte)PageDataType.Leaf)
  321. if (childType == (Byte)NodeChildType.Leaf)
  322. data = new Node(address, typeof(Leaf), page.Data);
  323. else if (childType == (Byte)NodeChildType.Node)
  324. data = new Node(address, typeof(Node), page.Data);
  325. else if (childType == (Byte)NodeChildType.Record)
  326. data = new Leaf(address, page.Data);
  327. else
  328. throw new Exception("Not a node");
  329. else if (type == (Byte)PageDataType.Record)
  330. data = new Record(address, page.Data);
  331. else if (type == (Byte)PageDataType.IndexUnitSector)
  332. data = new Sector(address, page.Data);
  333. else
  334. throw new Exception("Not valid Page Data");
  335. CacheOverflowCheck();
  336. return data;
  337. }
  338. protected virtual void WritePageToMemory(Page page)
  339. {
  340. StorageReader.Seek(page.Address, SeekOrigin.Begin);
  341. StorageReader.Write(page.Data, 0, Constants.PAGE_SIZE);
  342. if (PageWrite != null)
  343. PageWrite(this, new LRUCacheEventArgs(page));
  344. }
  345. #endregion
  346. }
  347. }