internal void WriteByteArrayTo(IJournalledResource data, long position, byte[] buf, int off, int len) { if (PARANOID_CHECKS) { lock (write_lock) { if (write_lock_count == 0) { Console.Out.WriteLine("Write without a Lock!"); Console.Out.WriteLine(new ApplicationException().StackTrace); } } } long page_number = position / page_size; int start_offset = (int)(position % page_size); int to_write = System.Math.Min(len, page_size - start_offset); BMPage page = FetchPage(data, page_number); lock (page) { try { page.Initialize(); page.Write(start_offset, buf, off, to_write); } finally { page.Dispose(); } } len -= to_write; while (len > 0) { off += to_write; position += to_write; ++page_number; to_write = System.Math.Min(len, page_size); page = FetchPage(data, page_number); lock (page) { try { page.Initialize(); page.Write(0, buf, off, to_write); } finally { page.Dispose(); } } len -= to_write; } }
internal void WriteByteTo(IJournalledResource data, long position, int b) { if (PARANOID_CHECKS) { lock (write_lock) { if (write_lock_count == 0) { Console.Out.WriteLine("Write without a Lock!"); Console.Out.WriteLine(new ApplicationException().StackTrace); } } } long page_number = position / page_size; BMPage page = FetchPage(data, page_number); lock (page) { try { page.Initialize(); page.Write((int)(position % page_size), (byte)b); } finally { page.Dispose(); } } }
internal int ReadByteArrayFrom(IJournalledResource data, long position, byte[] buf, int off, int len) { int orig_len = len; long page_number = position / page_size; int start_offset = (int)(position % page_size); int to_read = System.Math.Min(len, page_size - start_offset); BMPage page = FetchPage(data, page_number); lock (page) { try { page.Initialize(); page.Read(start_offset, buf, off, to_read); } finally { page.Dispose(); } } len -= to_read; while (len > 0) { off += to_read; position += to_read; ++page_number; to_read = System.Math.Min(len, page_size); page = FetchPage(data, page_number); lock (page) { try { page.Initialize(); page.Read(0, buf, off, to_read); } finally { page.Dispose(); } } len -= to_read; } return(orig_len); }
// ------ // Buffered access methods. These are all thread safe methods. When a page // is accessed the page is synchronized so no 2 or more operations can // Read/Write from the page at the same time. An operation can Read/Write to // different pages at the same time, however, and this requires thread safety // at a lower level (in the IJournalledResource implementation). // ------ internal int ReadByteFrom(IJournalledResource data, long position) { long page_number = position / page_size; int v; BMPage page = FetchPage(data, page_number); lock (page) { try { page.Initialize(); v = ((int)page.Read((int)(position % page_size))) & 0x0FF; } finally { page.Dispose(); } } return(v); }
/// <summary> /// Called when a new page is created. /// </summary> /// <param name="page"></param> private void PageCreated(BMPage page) { // lock (T_lock) { if (PARANOID_CHECKS) { int i = page_list.IndexOf(page); if (i != -1) { BMPage f = (BMPage)page_list[i]; if (f == page) { throw new ApplicationException("Same page added multiple times."); } if (f != null) { throw new ApplicationException("Duplicate pages."); } } } page.t = current_T; ++current_T; ++current_page_count; page_list.Add(page); // Below is the page purge algorithm. If the maximum number of pages // has been created we sort the page list weighting each page by time // since last accessed and total number of accesses and clear the bottom // 20% of this list. // Check if we should purge old pages and purge some if we do... if (current_page_count > max_pages) { // Purge 20% of the cache // Sort the pages by the current formula, // ( 1 / page_access_count ) * (current_t - page_t) // Further, if the page has written data then we multiply by 0.75. // This scales down page writes so they have a better chance of // surviving in the cache than page writes. Object[] pages = page_list.ToArray(); Array.Sort(pages, PageCacheComparer); int purge_size = System.Math.Max((int)(pages.Length * 0.20f), 2); for (int i = 0; i < purge_size; ++i) { BMPage dpage = (BMPage)pages[pages.Length - (i + 1)]; lock (dpage) { dpage.Dispose(); } } // Remove all the elements from page_list and set it with the sorted // list (minus the elements we removed). page_list.Clear(); for (int i = 0; i < pages.Length - purge_size; ++i) { page_list.Add(pages[i]); } current_page_count -= purge_size; } // } }